From 64e64191cbe64690676727d8e8f78a2db54b573c Mon Sep 17 00:00:00 2001 From: Thomas Wisniewski Date: Mon, 4 Mar 2024 21:34:27 +0000 Subject: [PATCH] Bug 1847358 part 3: add a fullMimeType attribute to nsIBaseChannel and use it to make our Data URI content-type header parsing standards-compliant for XHR and Fetch; r=dlrobertson,necko-reviewers,jesup Differential Revision: https://phabricator.services.mozilla.com/D203380 --- dom/base/BodyUtil.cpp | 2 +- dom/base/MimeType.cpp | 14 +-- dom/base/MimeType.h | 9 +- dom/base/test/gtest/TestMimeType.cpp | 142 ++++++++++++------------ dom/fetch/FetchDriver.cpp | 16 +-- dom/xhr/XMLHttpRequestMainThread.cpp | 18 +-- netwerk/base/nsBaseChannel.cpp | 12 ++ netwerk/base/nsBaseChannel.h | 2 + netwerk/base/nsIBaseChannel.idl | 15 +++ netwerk/protocol/data/nsDataChannel.cpp | 5 +- netwerk/protocol/data/nsDataChannel.h | 4 - netwerk/protocol/data/nsDataHandler.cpp | 13 ++- netwerk/protocol/data/nsDataHandler.h | 3 +- 13 files changed, 143 insertions(+), 112 deletions(-) diff --git a/dom/base/BodyUtil.cpp b/dom/base/BodyUtil.cpp index e5d86a3c36d6..1f35c895c7b5 100644 --- a/dom/base/BodyUtil.cpp +++ b/dom/base/BodyUtil.cpp @@ -267,7 +267,7 @@ class MOZ_STACK_CLASS FormDataParser { } // Determine boundary from mimetype. - UniquePtr parsed = CMimeType::Parse(mMixedCaseMimeType); + RefPtr parsed = CMimeType::Parse(mMixedCaseMimeType); if (!parsed) { return false; } diff --git a/dom/base/MimeType.cpp b/dom/base/MimeType.cpp index c5869b1d8a1a..da61489c1fe6 100644 --- a/dom/base/MimeType.cpp +++ b/dom/base/MimeType.cpp @@ -9,8 +9,8 @@ #include "nsUnicharUtils.h" template -/* static */ mozilla::UniquePtr> -TMimeType::Parse(const nsTSubstring& aMimeType) { +/* static */ RefPtr> TMimeType::Parse( + const nsTSubstring& aMimeType) { // See https://mimesniff.spec.whatwg.org/#parsing-a-mime-type // Steps 1-2 @@ -85,8 +85,8 @@ TMimeType::Parse(const nsTSubstring& aMimeType) { for (const char_type* c = subtypeStart; c < subtypeEnd; ++c) { subtype.Append(ToLowerCaseASCII(*c)); } - mozilla::UniquePtr> mimeType( - mozilla::MakeUnique>(type, subtype)); + RefPtr> mimeType = + new TMimeType(type, subtype); // Step 11 while (pos < end) { @@ -274,7 +274,7 @@ template static char_type kCHARSET[] = {'c', 'h', 'a', 'r', 's', 'e', 't'}; static nsTDependentSubstring kCharset(kCHARSET, 7); - mozilla::UniquePtr> parsed; + RefPtr> parsed; nsTAutoString prevContentType; nsTAutoString prevCharset; @@ -398,9 +398,9 @@ void TMimeType::SetParameterValue( }); } -template mozilla::UniquePtr> TMimeType::Parse( +template RefPtr> TMimeType::Parse( const nsTSubstring& aMimeType); -template mozilla::UniquePtr> TMimeType::Parse( +template RefPtr> TMimeType::Parse( const nsTSubstring& aMimeType); template bool TMimeType::Parse( const nsTSubstring& aMimeType, diff --git a/dom/base/MimeType.h b/dom/base/MimeType.h index 8c980c7f631a..a8b23dfa9bcf 100644 --- a/dom/base/MimeType.h +++ b/dom/base/MimeType.h @@ -8,7 +8,6 @@ #define mozilla_dom_MimeType_h #include "mozilla/TextUtils.h" -#include "mozilla/UniquePtr.h" #include "nsTHashMap.h" #include "nsTArray.h" @@ -26,6 +25,8 @@ struct HashKeyType { template class TMimeType final { private: + ~TMimeType() = default; + class ParameterValue : public nsTString { public: bool mRequiresQuoting; @@ -48,8 +49,8 @@ class TMimeType final { const nsTSubstring& aSubtype) : mType(aType), mSubtype(aSubtype) {} - static mozilla::UniquePtr> Parse( - const nsTSubstring& aStr); + static RefPtr> Parse( + const nsTSubstring& aMimeType); // @param aMimeType - the mimetype string // @param aOutEssence - will hold the value of the content-type @@ -84,6 +85,8 @@ class TMimeType final { // @param aValue - the value of the parameter void SetParameterValue(const nsTSubstring& aName, const nsTSubstring& aValue); + + NS_INLINE_DECL_REFCOUNTING(TMimeType) }; using MimeType = TMimeType; diff --git a/dom/base/test/gtest/TestMimeType.cpp b/dom/base/test/gtest/TestMimeType.cpp index fecb3f867857..40916130a8c1 100644 --- a/dom/base/test/gtest/TestMimeType.cpp +++ b/dom/base/test/gtest/TestMimeType.cpp @@ -9,12 +9,10 @@ #include "MimeType.h" #include "nsString.h" -using mozilla::UniquePtr; - TEST(MimeType, EmptyString) { const auto in = u""_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Empty string"; } @@ -22,7 +20,7 @@ TEST(MimeType, EmptyString) TEST(MimeType, JustWhitespace) { const auto in = u" \t\r\n "_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Just whitespace"; } @@ -30,7 +28,7 @@ TEST(MimeType, JustWhitespace) TEST(MimeType, JustBackslash) { const auto in = u"\\"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Just backslash"; } @@ -38,7 +36,7 @@ TEST(MimeType, JustBackslash) TEST(MimeType, JustForwardslash) { const auto in = u"/"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Just forward slash"; } @@ -46,7 +44,7 @@ TEST(MimeType, JustForwardslash) TEST(MimeType, MissingType1) { const auto in = u"/bogus"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Missing type #1"; } @@ -54,7 +52,7 @@ TEST(MimeType, MissingType1) TEST(MimeType, MissingType2) { const auto in = u" \r\n\t/bogus"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Missing type #2"; } @@ -62,7 +60,7 @@ TEST(MimeType, MissingType2) TEST(MimeType, MissingSubtype1) { const auto in = u"bogus"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Missing subtype #1"; } @@ -70,7 +68,7 @@ TEST(MimeType, MissingSubtype1) TEST(MimeType, MissingSubType2) { const auto in = u"bogus/"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Missing subtype #2"; } @@ -78,7 +76,7 @@ TEST(MimeType, MissingSubType2) TEST(MimeType, MissingSubType3) { const auto in = u"bogus;"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Missing subtype #3"; } @@ -86,7 +84,7 @@ TEST(MimeType, MissingSubType3) TEST(MimeType, MissingSubType4) { const auto in = u"bogus; \r\n\t"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Missing subtype #3"; } @@ -94,7 +92,7 @@ TEST(MimeType, MissingSubType4) TEST(MimeType, ExtraForwardSlash) { const auto in = u"bogus/bogus/;"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Extra forward slash"; } @@ -102,7 +100,7 @@ TEST(MimeType, ExtraForwardSlash) TEST(MimeType, WhitespaceInType) { const auto in = u"t\re\nx\tt /html"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Type with whitespace"; } @@ -110,7 +108,7 @@ TEST(MimeType, WhitespaceInType) TEST(MimeType, WhitespaceInSubtype) { const auto in = u"text/ h\rt\nm\tl"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Subtype with whitespace"; } @@ -118,7 +116,7 @@ TEST(MimeType, WhitespaceInSubtype) TEST(MimeType, NonAlphanumericMediaType1) { const auto in = u""_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Non-alphanumeric media type #1"; } @@ -126,7 +124,7 @@ TEST(MimeType, NonAlphanumericMediaType1) TEST(MimeType, NonAlphanumericMediaType2) { const auto in = u"(/)"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Non-alphanumeric media type #2"; } @@ -134,7 +132,7 @@ TEST(MimeType, NonAlphanumericMediaType2) TEST(MimeType, NonAlphanumericMediaType3) { const auto in = u"{/}"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Non-alphanumeric media type #3"; } @@ -142,7 +140,7 @@ TEST(MimeType, NonAlphanumericMediaType3) TEST(MimeType, NonAlphanumericMediaType4) { const auto in = u"\"/\""_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Non-alphanumeric media type #4"; } @@ -150,7 +148,7 @@ TEST(MimeType, NonAlphanumericMediaType4) TEST(MimeType, NonAlphanumericMediaType5) { const auto in = u"\0/\0"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Non-alphanumeric media type #5"; } @@ -158,7 +156,7 @@ TEST(MimeType, NonAlphanumericMediaType5) TEST(MimeType, NonAlphanumericMediaType6) { const auto in = u"text/html(;doesnot=matter"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Non-alphanumeric media type #6"; } @@ -166,7 +164,7 @@ TEST(MimeType, NonAlphanumericMediaType6) TEST(MimeType, NonLatin1MediaType1) { const auto in = u"ÿ/ÿ"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Non-latin1 media type #1"; } @@ -174,7 +172,7 @@ TEST(MimeType, NonLatin1MediaType1) TEST(MimeType, NonLatin1MediaType2) { const auto in = u"\x0100/\x0100"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_FALSE(parsed) << "Non-latin1 media type #2"; } @@ -182,7 +180,7 @@ TEST(MimeType, NonLatin1MediaType2) TEST(MimeType, MultipleParameters) { const auto in = u"text/html;charset=gbk;no=1;charset_=gbk_;yes=2"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsString out; @@ -194,7 +192,7 @@ TEST(MimeType, MultipleParameters) TEST(MimeType, DuplicateParameter1) { const auto in = u"text/html;charset=gbk;charset=windows-1255"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsString out; @@ -206,7 +204,7 @@ TEST(MimeType, DuplicateParameter1) TEST(MimeType, DuplicateParameter2) { const auto in = u"text/html;charset=();charset=GBK"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsString out; @@ -218,7 +216,7 @@ TEST(MimeType, DuplicateParameter2) TEST(MimeType, CString) { const auto in = "text/html;charset=();charset=GBK"_ns; - UniquePtr parsed = CMimeType::Parse(in); + RefPtr parsed = CMimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsCString out; @@ -234,7 +232,7 @@ TEST(MimeType, CString) TEST(MimeType, NonAlphanumericParametersAreQuoted) { const auto in = u"text/html;test=\x00FF\\;charset=gbk"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsString out; @@ -249,7 +247,7 @@ TEST(MimeType, NonAlphanumericParametersAreQuoted) TEST(MimeType, ParameterQuotedIfHasLeadingWhitespace1) { const auto in = u"text/html;charset= g\\\"bk"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -261,7 +259,7 @@ TEST(MimeType, ParameterQuotedIfHasLeadingWhitespace1) TEST(MimeType, ParameterQuotedIfHasLeadingWhitespace2) { const auto in = u"text/html;charset= \"g\\bk\""_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -273,7 +271,7 @@ TEST(MimeType, ParameterQuotedIfHasLeadingWhitespace2) TEST(MimeType, ParameterQuotedIfHasInternalWhitespace) { const auto in = u"text/html;charset=g \\b\"k"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -285,7 +283,7 @@ TEST(MimeType, ParameterQuotedIfHasInternalWhitespace) TEST(MimeType, ImproperlyQuotedParameter1) { const auto in = u"x/x;test=\""_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -297,7 +295,7 @@ TEST(MimeType, ImproperlyQuotedParameter1) TEST(MimeType, ImproperlyQuotedParameter2) { const auto in = u"x/x;test=\"\\"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -309,7 +307,7 @@ TEST(MimeType, ImproperlyQuotedParameter2) TEST(MimeType, NonLatin1ParameterIgnored) { const auto in = u"x/x;test=\xFFFD;x=x"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -321,7 +319,7 @@ TEST(MimeType, NonLatin1ParameterIgnored) TEST(MimeType, ParameterIgnoredIfWhitespaceInName1) { const auto in = u"text/html;charset =gbk;charset=123"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -333,7 +331,7 @@ TEST(MimeType, ParameterIgnoredIfWhitespaceInName1) TEST(MimeType, ParameterIgnoredIfWhitespaceInName2) { const auto in = u"text/html;cha rset =gbk;charset=123"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -345,7 +343,7 @@ TEST(MimeType, ParameterIgnoredIfWhitespaceInName2) TEST(MimeType, WhitespaceTrimmed) { const auto in = u"\n\r\t text/plain\n\r\t ;\n\r\t charset=123\n\r\t "_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -357,7 +355,7 @@ TEST(MimeType, WhitespaceTrimmed) TEST(MimeType, WhitespaceOnlyParameterIgnored) { const auto in = u"x/x;x= \r\n\t"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -369,7 +367,7 @@ TEST(MimeType, WhitespaceOnlyParameterIgnored) TEST(MimeType, IncompleteParameterIgnored1) { const auto in = u"x/x;test"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -381,7 +379,7 @@ TEST(MimeType, IncompleteParameterIgnored1) TEST(MimeType, IncompleteParameterIgnored2) { const auto in = u"x/x;test="_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -393,7 +391,7 @@ TEST(MimeType, IncompleteParameterIgnored2) TEST(MimeType, IncompleteParameterIgnored3) { const auto in = u"x/x;test= \r\n\t"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -405,7 +403,7 @@ TEST(MimeType, IncompleteParameterIgnored3) TEST(MimeType, IncompleteParameterIgnored4) { const auto in = u"text/html;test;charset=gbk"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -417,7 +415,7 @@ TEST(MimeType, IncompleteParameterIgnored4) TEST(MimeType, IncompleteParameterIgnored5) { const auto in = u"text/html;test=;charset=gbk"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -429,7 +427,7 @@ TEST(MimeType, IncompleteParameterIgnored5) TEST(MimeType, EmptyParameterIgnored1) { const auto in = u"text/html ; ; charset=gbk"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -441,7 +439,7 @@ TEST(MimeType, EmptyParameterIgnored1) TEST(MimeType, EmptyParameterIgnored2) { const auto in = u"text/html;;;;charset=gbk"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -453,7 +451,7 @@ TEST(MimeType, EmptyParameterIgnored2) TEST(MimeType, InvalidParameterIgnored1) { const auto in = u"text/html;';charset=gbk"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -465,7 +463,7 @@ TEST(MimeType, InvalidParameterIgnored1) TEST(MimeType, InvalidParameterIgnored2) { const auto in = u"text/html;\";charset=gbk;=123; =321"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -477,7 +475,7 @@ TEST(MimeType, InvalidParameterIgnored2) TEST(MimeType, InvalidParameterIgnored3) { const auto in = u"text/html;charset= \"\u007F;charset=GBK"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -490,7 +488,7 @@ TEST(MimeType, InvalidParameterIgnored4) { const auto in = nsLiteralString( u"text/html;charset=\"\u007F;charset=foo\";charset=GBK;charset="); - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -502,7 +500,7 @@ TEST(MimeType, InvalidParameterIgnored4) TEST(MimeType, SingleQuotes1) { const auto in = u"text/html;charset='gbk'"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -514,7 +512,7 @@ TEST(MimeType, SingleQuotes1) TEST(MimeType, SingleQuotes2) { const auto in = u"text/html;charset='gbk"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -526,7 +524,7 @@ TEST(MimeType, SingleQuotes2) TEST(MimeType, SingleQuotes3) { const auto in = u"text/html;charset=gbk'"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -538,7 +536,7 @@ TEST(MimeType, SingleQuotes3) TEST(MimeType, SingleQuotes4) { const auto in = u"text/html;charset=';charset=GBK"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -550,7 +548,7 @@ TEST(MimeType, SingleQuotes4) TEST(MimeType, SingleQuotes5) { const auto in = u"text/html;charset=''';charset=GBK"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -562,7 +560,7 @@ TEST(MimeType, SingleQuotes5) TEST(MimeType, DoubleQuotes1) { const auto in = u"text/html;charset=\"gbk\""_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -574,7 +572,7 @@ TEST(MimeType, DoubleQuotes1) TEST(MimeType, DoubleQuotes2) { const auto in = u"text/html;charset=\"gbk"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -586,7 +584,7 @@ TEST(MimeType, DoubleQuotes2) TEST(MimeType, DoubleQuotes3) { const auto in = u"text/html;charset=gbk\""_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -598,7 +596,7 @@ TEST(MimeType, DoubleQuotes3) TEST(MimeType, DoubleQuotes4) { const auto in = u"text/html;charset=\" gbk\""_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -610,7 +608,7 @@ TEST(MimeType, DoubleQuotes4) TEST(MimeType, DoubleQuotes5) { const auto in = u"text/html;charset=\"gbk \""_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -622,7 +620,7 @@ TEST(MimeType, DoubleQuotes5) TEST(MimeType, DoubleQuotes6) { const auto in = u"text/html;charset=\"\\ gbk\""_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -634,7 +632,7 @@ TEST(MimeType, DoubleQuotes6) TEST(MimeType, DoubleQuotes7) { const auto in = u"text/html;charset=\"\\g\\b\\k\""_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -646,7 +644,7 @@ TEST(MimeType, DoubleQuotes7) TEST(MimeType, DoubleQuotes8) { const auto in = u"text/html;charset=\"gbk\"x"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -658,7 +656,7 @@ TEST(MimeType, DoubleQuotes8) TEST(MimeType, DoubleQuotes9) { const auto in = u"text/html;charset=\"\";charset=GBK"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -670,7 +668,7 @@ TEST(MimeType, DoubleQuotes9) TEST(MimeType, DoubleQuotes10) { const auto in = u"text/html;charset=\";charset=GBK"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -682,7 +680,7 @@ TEST(MimeType, DoubleQuotes10) TEST(MimeType, UnexpectedCodePoints) { const auto in = u"text/html;charset={gbk}"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -699,7 +697,7 @@ TEST(MimeType, LongTypesSubtypesAccepted) "2345678901234567890123456789012345678901234567890123456789/" "012345678901234567890123456789012345678901234567890123456789012345678901" "2345678901234567890123456789012345678901234567890123456789"); - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -716,7 +714,7 @@ TEST(MimeType, LongParametersAccepted) "012345678901234567890123456789012345678901234567890123456789012345678901" "2345678901234567890123456789012345678901234567890123456789=x;charset=" "gbk"); - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -744,7 +742,7 @@ TEST(MimeType, AllValidCharactersAccepted1) u"\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED" u"\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8" u"\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF\""); - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -756,7 +754,7 @@ TEST(MimeType, AllValidCharactersAccepted1) TEST(MimeType, CaseNormalization1) { const auto in = u"TEXT/PLAIN;CHARSET=TEST"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -775,7 +773,7 @@ TEST(MimeType, CaseNormalization2) ".^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$" "%&'*+-.^_`|~" "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -794,7 +792,7 @@ TEST(MimeType, CaseNormalization2) TEST(MimeType, LegacyCommentSyntax1) { const auto in = u"text/html;charset=gbk("_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; @@ -806,7 +804,7 @@ TEST(MimeType, LegacyCommentSyntax1) TEST(MimeType, LegacyCommentSyntax2) { const auto in = u"text/html;x=(;charset=gbk"_ns; - UniquePtr parsed = MimeType::Parse(in); + RefPtr parsed = MimeType::Parse(in); ASSERT_TRUE(parsed) << "Parsing succeeded"; nsAutoString out; diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index 7551aa0e1012..c4acc35cf5f2 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -1039,7 +1039,7 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest) { bool foundOpaqueRedirect = false; - nsAutoCString contentType; + nsAutoCString contentType(VoidCString()); int64_t contentLength = InternalResponse::UNKNOWN_BODY_SIZE; rv = channel->GetContentLength(&contentLength); @@ -1119,13 +1119,13 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest) { MOZ_ASSERT(!result.Failed()); } - nsCOMPtr uri; - channel->GetURI(getter_AddRefs(uri)); - if (uri && uri->SchemeIs("data")) { - nsDataChannel* dchan = static_cast(channel.get()); - MOZ_ASSERT(dchan); - contentType.Assign(dchan->MimeType()); - } else { + if (baseChan) { + RefPtr fullMimeType(baseChan->FullMimeType()); + if (fullMimeType) { + fullMimeType->Serialize(contentType); + } + } + if (contentType.IsVoid()) { channel->GetContentType(contentType); if (!contentType.IsEmpty()) { nsAutoCString contentCharset; diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp index 4c9822dff1db..c83e034551a6 100644 --- a/dom/xhr/XMLHttpRequestMainThread.cpp +++ b/dom/xhr/XMLHttpRequestMainThread.cpp @@ -1208,13 +1208,13 @@ bool XMLHttpRequestMainThread::IsSafeHeader( bool XMLHttpRequestMainThread::GetContentType(nsACString& aValue) const { MOZ_ASSERT(mChannel); - nsCOMPtr uri; - if (NS_SUCCEEDED(mChannel->GetURI(getter_AddRefs(uri))) && - uri->SchemeIs("data")) { - nsDataChannel* dchan = static_cast(mChannel.get()); - MOZ_ASSERT(dchan); - aValue.Assign(dchan->MimeType()); - return true; + nsCOMPtr baseChan = do_QueryInterface(mChannel); + if (baseChan) { + RefPtr fullMimeType(baseChan->FullMimeType()); + if (fullMimeType) { + fullMimeType->Serialize(aValue); + return true; + } } if (NS_SUCCEEDED(mChannel->GetContentType(aValue))) { nsCString value; @@ -3141,7 +3141,7 @@ void XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody, if (uploadContentType.IsVoid()) { uploadContentType = defaultContentType; } else if (aBodyIsDocumentOrString) { - UniquePtr contentTypeRecord = + RefPtr contentTypeRecord = CMimeType::Parse(uploadContentType); nsAutoCString charset; if (contentTypeRecord && @@ -3404,7 +3404,7 @@ void XMLHttpRequestMainThread::OverrideMimeType(const nsAString& aMimeType, return; } - UniquePtr parsed = MimeType::Parse(aMimeType); + RefPtr parsed = MimeType::Parse(aMimeType); if (parsed) { parsed->Serialize(mOverrideMimeType); } else { diff --git a/netwerk/base/nsBaseChannel.cpp b/netwerk/base/nsBaseChannel.cpp index d3d71fb089f2..2671b5886a2e 100644 --- a/netwerk/base/nsBaseChannel.cpp +++ b/netwerk/base/nsBaseChannel.cpp @@ -980,3 +980,15 @@ NS_IMETHODIMP nsBaseChannel::SetContentRange( mContentRange = aRange; return NS_OK; } + +NS_IMETHODIMP nsBaseChannel::GetFullMimeType(RefPtr>* aOut) { + if (aOut) { + *aOut = mFullMimeType; + } + return NS_OK; +} + +NS_IMETHODIMP nsBaseChannel::SetFullMimeType(RefPtr> aType) { + mFullMimeType = aType; + return NS_OK; +} diff --git a/netwerk/base/nsBaseChannel.h b/netwerk/base/nsBaseChannel.h index 6b0b6797ba61..c0db8e2500ae 100644 --- a/netwerk/base/nsBaseChannel.h +++ b/netwerk/base/nsBaseChannel.h @@ -6,6 +6,7 @@ #ifndef nsBaseChannel_h__ #define nsBaseChannel_h__ +#include "mozilla/dom/MimeType.h" #include "mozilla/Maybe.h" #include "mozilla/MozPromise.h" #include "mozilla/UniquePtr.h" @@ -292,6 +293,7 @@ class nsBaseChannel bool mOpenRedirectChannel{false}; uint32_t mRedirectFlags{0}; RefPtr mContentRange; + RefPtr mFullMimeType; protected: nsCString mContentType; diff --git a/netwerk/base/nsIBaseChannel.idl b/netwerk/base/nsIBaseChannel.idl index d80e8c59d92f..5f2fe1517de4 100644 --- a/netwerk/base/nsIBaseChannel.idl +++ b/netwerk/base/nsIBaseChannel.idl @@ -5,6 +5,7 @@ #include "nsISupports.idl" %{C++ +#include "mozilla/dom/MimeType.h" #include "mozilla/net/ContentRange.h" %} @@ -17,6 +18,7 @@ */ native ContentRangeRef(RefPtr); +native MimeTypeRef(RefPtr>); [uuid(036d5cd7-9a53-40e3-9c72-c2ffaa15aa2b)] interface nsIBaseChannel : nsISupports { @@ -27,6 +29,13 @@ interface nsIBaseChannel : nsISupports { */ attribute ContentRangeRef contentRange; + /** + * Used by fetch and XMLHttpRequest to get the standards-compliant value they + * should set for the Content-Type header on response (if nullptr, they will + * use Firefox-specific values from nsIChannel::GetContentType and GetCharset). + */ + attribute MimeTypeRef fullMimeType; + %{C++ RefPtr ContentRange() { RefPtr range; @@ -43,6 +52,12 @@ interface nsIBaseChannel : nsISupports { SetContentRange(range); return true; } + + RefPtr FullMimeType() { + RefPtr type; + mozilla::Unused << GetFullMimeType(&type); + return type; + } %} }; diff --git a/netwerk/protocol/data/nsDataChannel.cpp b/netwerk/protocol/data/nsDataChannel.cpp index 87b00adea3ae..df40971e1c43 100644 --- a/netwerk/protocol/data/nsDataChannel.cpp +++ b/netwerk/protocol/data/nsDataChannel.cpp @@ -8,6 +8,7 @@ #include "nsDataChannel.h" #include "mozilla/Base64.h" +#include "mozilla/dom/MimeType.h" #include "nsDataHandler.h" #include "nsIInputStream.h" #include "nsEscape.h" @@ -59,9 +60,10 @@ nsresult nsDataChannel::OpenContentStream(bool async, nsIInputStream** result, nsCString contentType, contentCharset; nsDependentCSubstring dataRange; + RefPtr fullMimeType; bool lBase64; rv = nsDataHandler::ParsePathWithoutRef(path, contentType, &contentCharset, - lBase64, &dataRange, &mMimeType); + lBase64, &dataRange, &fullMimeType); if (NS_FAILED(rv)) return rv; // This will avoid a copy if nothing needs to be unescaped. @@ -103,6 +105,7 @@ nsresult nsDataChannel::OpenContentStream(bool async, nsIInputStream** result, SetContentType(contentType); SetContentCharset(contentCharset); + SetFullMimeType(std::move(fullMimeType)); mContentLength = contentLen; // notify "data-channel-opened" observers diff --git a/netwerk/protocol/data/nsDataChannel.h b/netwerk/protocol/data/nsDataChannel.h index d7313d66a0fd..f7700ff2b4ed 100644 --- a/netwerk/protocol/data/nsDataChannel.h +++ b/netwerk/protocol/data/nsDataChannel.h @@ -16,14 +16,10 @@ class nsDataChannel : public nsBaseChannel { public: explicit nsDataChannel(nsIURI* uri) { SetURI(uri); } - const nsACString& MimeType() const { return mMimeType; } - protected: [[nodiscard]] virtual nsresult OpenContentStream( bool async, nsIInputStream** result, nsIChannel** channel) override; - nsCString mMimeType; - private: nsresult MaybeSendDataChannelOpenNotification(); }; diff --git a/netwerk/protocol/data/nsDataHandler.cpp b/netwerk/protocol/data/nsDataHandler.cpp index d3a5743097e8..adb86bf484b1 100644 --- a/netwerk/protocol/data/nsDataHandler.cpp +++ b/netwerk/protocol/data/nsDataHandler.cpp @@ -161,7 +161,7 @@ nsresult nsDataHandler::ParsePathWithoutRef(const nsACString& aPath, nsCString* aContentCharset, bool& aIsBase64, nsDependentCSubstring* aDataBuffer, - nsCString* aMimeType) { + RefPtr* aMimeType) { static constexpr auto kCharset = "charset"_ns; // This implements https://fetch.spec.whatwg.org/#data-url-processor @@ -200,18 +200,18 @@ nsresult nsDataHandler::ParsePathWithoutRef(const nsACString& aPath, // This also checks for instances of ;base64 in the middle of the MimeType. // This is against the current spec, but we're doing it because we have // historically seen webcompat issues relying on this (see bug 781693). - if (mozilla::UniquePtr parsed = CMimeType::Parse(mimeType)) { + if (RefPtr parsed = CMimeType::Parse(mimeType)) { parsed->GetEssence(aContentType); if (aContentCharset) { parsed->GetParameterValue(kCharset, *aContentCharset); } - if (aMimeType) { - parsed->Serialize(*aMimeType); - } if (parsed->IsBase64() && !StaticPrefs::network_url_strict_data_url_base64_placement()) { aIsBase64 = true; } + if (aMimeType) { + *aMimeType = std::move(parsed); + } } else { // "If mimeTypeRecord is failure, then set mimeTypeRecord to // text/plain;charset=US-ASCII." @@ -220,7 +220,8 @@ nsresult nsDataHandler::ParsePathWithoutRef(const nsACString& aPath, aContentCharset->AssignLiteral("US-ASCII"); } if (aMimeType) { - aMimeType->AssignLiteral("text/plain;charset=US-ASCII"); + *aMimeType = new CMimeType("text"_ns, "plain"_ns); + (*aMimeType)->SetParameterValue("charset"_ns, "US-ASCII"_ns); } } diff --git a/netwerk/protocol/data/nsDataHandler.h b/netwerk/protocol/data/nsDataHandler.h index 4796f0f453d7..499e73b220cf 100644 --- a/netwerk/protocol/data/nsDataHandler.h +++ b/netwerk/protocol/data/nsDataHandler.h @@ -6,6 +6,7 @@ #ifndef nsDataHandler_h___ #define nsDataHandler_h___ +#include "mozilla/dom/MimeType.h" #include "nsIProtocolHandler.h" #include "nsWeakReference.h" @@ -50,7 +51,7 @@ class nsDataHandler : public nsIProtocolHandler, [[nodiscard]] static nsresult ParsePathWithoutRef( const nsACString& aPath, nsCString& aContentType, nsCString* aContentCharset, bool& aIsBase64, - nsDependentCSubstring* aDataBuffer, nsCString* aMimeType = nullptr); + nsDependentCSubstring* aDataBuffer, RefPtr* = nullptr); }; #endif /* nsDataHandler_h___ */