blob: 7a83352d17b9c7fe4ee40a2dd312e846f42f4361 [file] [log] [blame]
Avi Drissman64595482022-09-14 20:52:291// Copyright 2012 The Chromium Authors
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
eromanf6ef682612017-01-31 19:12:025#include "net/base/mime_util.h"
6
Arthur Sonzognib08180bb2021-11-24 10:00:447#include <vector>
8
Lei Zhangde197672021-04-29 08:11:249#include "base/containers/contains.h"
[email protected]d778e0422013-03-06 18:10:2210#include "base/strings/string_split.h"
[email protected]750b2f3c2013-06-07 18:41:0511#include "base/strings/utf_string_conversions.h"
servolkf3955532015-05-16 00:01:5912#include "build/build_config.h"
Yuta Hijikata101ed2a2020-11-18 07:50:3913#include "build/chromeos_buildflags.h"
Arthur Sonzognib08180bb2021-11-24 10:00:4414#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:5215#include "testing/gtest/include/gtest/gtest.h"
16
[email protected]8effd3f62011-03-25 16:29:0717namespace net {
initial.commit586acc5fe2008-07-26 22:42:5218
Arthur Sonzognib08180bb2021-11-24 10:00:4419using testing::Contains;
20
21TEST(MimeUtilTest, GetWellKnownMimeTypeFromExtension) {
22 // String: png\0css
23 base::FilePath::StringType containsNullByte;
24 containsNullByte.append(FILE_PATH_LITERAL("png"));
25 containsNullByte.append(1, FILE_PATH_LITERAL('\0'));
26 containsNullByte.append(FILE_PATH_LITERAL("css"));
27
28 const struct {
29 const base::FilePath::StringType extension;
30 const char* const mime_type;
31 } tests[] = {
32 {FILE_PATH_LITERAL("png"), "image/png"},
33 {FILE_PATH_LITERAL("PNG"), "image/png"},
34 {FILE_PATH_LITERAL("css"), "text/css"},
35 {FILE_PATH_LITERAL("pjp"), "image/jpeg"},
36 {FILE_PATH_LITERAL("pjpeg"), "image/jpeg"},
37 {FILE_PATH_LITERAL("json"), "application/json"},
38 {FILE_PATH_LITERAL("js"), "text/javascript"},
39 {FILE_PATH_LITERAL("webm"), "video/webm"},
40 {FILE_PATH_LITERAL("weba"), "audio/webm"},
41 {FILE_PATH_LITERAL("avif"), "image/avif"},
Arthur Sonzognib08180bb2021-11-24 10:00:4442 {FILE_PATH_LITERAL("epub"), "application/epub+zip"},
43 {FILE_PATH_LITERAL("apk"), "application/vnd.android.package-archive"},
44 {FILE_PATH_LITERAL("cer"), "application/x-x509-ca-cert"},
45 {FILE_PATH_LITERAL("crt"), "application/x-x509-ca-cert"},
46 {FILE_PATH_LITERAL("zip"), "application/zip"},
47 {FILE_PATH_LITERAL("ics"), "text/calendar"},
48 {FILE_PATH_LITERAL("m3u8"), "application/x-mpegurl"},
Eric Lawrenceb822a8e2022-02-02 19:03:4249 {FILE_PATH_LITERAL("csv"), "text/csv"},
Arthur Sonzognib08180bb2021-11-24 10:00:4450 {FILE_PATH_LITERAL("not an extension / for sure"), nullptr},
51 {containsNullByte, nullptr}};
52
53 for (const auto& test : tests) {
54 std::string mime_type;
55 if (GetWellKnownMimeTypeFromExtension(test.extension, &mime_type))
56 EXPECT_EQ(test.mime_type, mime_type);
57 else
58 EXPECT_EQ(test.mime_type, nullptr);
59 }
60}
61
initial.commit586acc5fe2008-07-26 22:42:5262TEST(MimeUtilTest, ExtensionTest) {
yawanoc8297362015-05-19 05:47:5963 // String: png\0css
64 base::FilePath::StringType containsNullByte;
65 containsNullByte.append(FILE_PATH_LITERAL("png"));
66 containsNullByte.append(1, FILE_PATH_LITERAL('\0'));
67 containsNullByte.append(FILE_PATH_LITERAL("css"));
68
initial.commit586acc5fe2008-07-26 22:42:5269 const struct {
yawanoc8297362015-05-19 05:47:5970 const base::FilePath::StringType extension;
Arthur Sonzognib08180bb2021-11-24 10:00:4471 const std::vector<std::string> mime_types;
initial.commit586acc5fe2008-07-26 22:42:5272 } tests[] = {
Arthur Sonzognib08180bb2021-11-24 10:00:4473 {FILE_PATH_LITERAL("png"), {"image/png"}},
74 {FILE_PATH_LITERAL("PNG"), {"image/png"}},
75 {FILE_PATH_LITERAL("css"), {"text/css"}},
76 {FILE_PATH_LITERAL("pjp"), {"image/jpeg"}},
77 {FILE_PATH_LITERAL("pjpeg"), {"image/jpeg"}},
78 {FILE_PATH_LITERAL("json"), {"application/json"}},
79 {FILE_PATH_LITERAL("js"), {"text/javascript"}},
80 {FILE_PATH_LITERAL("webm"), {"video/webm"}},
81 {FILE_PATH_LITERAL("weba"), {"audio/webm"}},
82 {FILE_PATH_LITERAL("avif"), {"image/avif"}},
Yuta Hijikata101ed2a2020-11-18 07:50:3983#if BUILDFLAG(IS_CHROMEOS_ASH)
Joel Hockeyb4a0c8b92022-08-30 04:33:0284 // These are test cases for testing platform mime types on ChromeOS.
Arthur Sonzognib08180bb2021-11-24 10:00:4485 {FILE_PATH_LITERAL("epub"), {"application/epub+zip"}},
86 {FILE_PATH_LITERAL("apk"), {"application/vnd.android.package-archive"}},
Joel Hockeyb4a0c8b92022-08-30 04:33:0287 {FILE_PATH_LITERAL("cer"),
88 {
89 "application/x-x509-ca-cert",
90 "application/pkix-cert", // System override for ChromeOS.
91 }},
92 {FILE_PATH_LITERAL("crt"),
93 {
94 "application/x-x509-ca-cert",
95 "application/pkix-cert", // System override for ChromeOS.
96 }},
Arthur Sonzognib08180bb2021-11-24 10:00:4497 {FILE_PATH_LITERAL("zip"), {"application/zip"}},
98 {FILE_PATH_LITERAL("ics"), {"text/calendar"}},
yawanoc8297362015-05-19 05:47:5999#endif
Arthur Sonzognib08180bb2021-11-24 10:00:44100 {FILE_PATH_LITERAL("m3u8"),
101 {
102 "application/x-mpegurl", // Chrome's secondary mapping.
103 "audio/x-mpegurl", // https://crbug.com/1273061, system override for
104 // android-arm[64]-test and Linux. Possibly more.
Joel Hockeyb4a0c8b92022-08-30 04:33:02105 "application/vnd.apple.mpegurl", // System override for ChromeOS.
106 "audio/mpegurl", // System override for mac.
Arthur Sonzognib08180bb2021-11-24 10:00:44107 }},
Eric Lawrenceb822a8e2022-02-02 19:03:42108 {FILE_PATH_LITERAL("csv"), {"text/csv"}},
Arthur Sonzognib08180bb2021-11-24 10:00:44109 {FILE_PATH_LITERAL("not an extension / for sure"), {}},
110 {containsNullByte, {}}
initial.commit586acc5fe2008-07-26 22:42:52111 };
112
Ryan Sleevi4625214fa2018-05-10 16:42:45113 for (const auto& test : tests) {
Arthur Sonzognib08180bb2021-11-24 10:00:44114 std::string mime_type;
115 if (GetMimeTypeFromExtension(test.extension, &mime_type))
116 EXPECT_THAT(test.mime_types, Contains(mime_type));
117 else
118 EXPECT_TRUE(test.mime_types.empty());
initial.commit586acc5fe2008-07-26 22:42:52119 }
120}
121
Asanka Herath5a9642452018-11-03 03:19:42122// Behavior of GetPreferredExtensionForMimeType() is dependent on the host
123// platform since the latter can override the mapping from file extensions to
124// MIME types. The tests below would only work if the platform MIME mappings
125// don't have mappings for or has an agreeing mapping for each MIME type
126// mentioned.
127TEST(MimeUtilTest, GetPreferredExtensionForMimeType) {
128 const struct {
129 const std::string mime_type;
130 const base::FilePath::StringType expected_extension;
131 } kTestCases[] = {
132 {"application/wasm", FILE_PATH_LITERAL("wasm")}, // Primary
133 {"application/javascript", FILE_PATH_LITERAL("js")}, // Secondary
134 {"text/javascript", FILE_PATH_LITERAL("js")}, // Primary
Asanka Herath5a9642452018-11-03 03:19:42135 {"video/webm", FILE_PATH_LITERAL("webm")}, // Primary
136 };
137
138 for (const auto& test : kTestCases) {
139 base::FilePath::StringType extension;
140 auto rv = GetPreferredExtensionForMimeType(test.mime_type, &extension);
141 EXPECT_TRUE(rv);
142 EXPECT_EQ(test.expected_extension, extension);
143 }
144}
145
initial.commit586acc5fe2008-07-26 22:42:52146TEST(MimeUtilTest, FileTest) {
147 const struct {
[email protected]6cdfd7f2013-02-08 20:40:15148 const base::FilePath::CharType* file_path;
thestig9d3bb0c2015-01-24 00:49:51149 const char* const mime_type;
initial.commit586acc5fe2008-07-26 22:42:52150 bool valid;
151 } tests[] = {
mtomasz7b54be12015-02-16 06:59:53152 {FILE_PATH_LITERAL("c:\\foo\\bar.css"), "text/css", true},
153 {FILE_PATH_LITERAL("c:\\foo\\bar.CSS"), "text/css", true},
154 {FILE_PATH_LITERAL("c:\\blah"), "", false},
155 {FILE_PATH_LITERAL("/usr/local/bin/mplayer"), "", false},
156 {FILE_PATH_LITERAL("/home/foo/bar.css"), "text/css", true},
157 {FILE_PATH_LITERAL("/blah."), "", false},
158 {FILE_PATH_LITERAL("c:\\blah."), "", false},
initial.commit586acc5fe2008-07-26 22:42:52159 };
160
161 std::string mime_type;
162 bool rv;
163
Ryan Sleevi4625214fa2018-05-10 16:42:45164 for (const auto& test : tests) {
165 rv = GetMimeTypeFromFile(base::FilePath(test.file_path), &mime_type);
166 EXPECT_EQ(test.valid, rv);
initial.commit586acc5fe2008-07-26 22:42:52167 if (rv)
Ryan Sleevi4625214fa2018-05-10 16:42:45168 EXPECT_EQ(test.mime_type, mime_type);
initial.commit586acc5fe2008-07-26 22:42:52169 }
170}
171
initial.commit586acc5fe2008-07-26 22:42:52172TEST(MimeUtilTest, MatchesMimeType) {
mtomasz7b54be12015-02-16 06:59:53173 // MIME types are case insensitive.
174 EXPECT_TRUE(MatchesMimeType("VIDEO/*", "video/x-mpeg"));
175 EXPECT_TRUE(MatchesMimeType("video/*", "VIDEO/X-MPEG"));
176
[email protected]8effd3f62011-03-25 16:29:07177 EXPECT_TRUE(MatchesMimeType("*", "video/x-mpeg"));
178 EXPECT_TRUE(MatchesMimeType("video/*", "video/x-mpeg"));
[email protected]87fbf192012-09-18 09:43:05179 EXPECT_TRUE(MatchesMimeType("video/*", "video/*"));
[email protected]8effd3f62011-03-25 16:29:07180 EXPECT_TRUE(MatchesMimeType("video/x-mpeg", "video/x-mpeg"));
181 EXPECT_TRUE(MatchesMimeType("application/*+xml",
[email protected]34f40942010-10-04 00:34:04182 "application/html+xml"));
[email protected]8effd3f62011-03-25 16:29:07183 EXPECT_TRUE(MatchesMimeType("application/*+xml", "application/+xml"));
[email protected]a698f822013-12-20 01:48:47184 EXPECT_TRUE(MatchesMimeType("application/*+json",
185 "application/x-myformat+json"));
[email protected]8effd3f62011-03-25 16:29:07186 EXPECT_TRUE(MatchesMimeType("aaa*aaa", "aaaaaa"));
[email protected]007b3f82013-04-09 08:46:45187 EXPECT_TRUE(MatchesMimeType("*", std::string()));
[email protected]8effd3f62011-03-25 16:29:07188 EXPECT_FALSE(MatchesMimeType("video/", "video/x-mpeg"));
mtomasz7b54be12015-02-16 06:59:53189 EXPECT_FALSE(MatchesMimeType("VIDEO/", "Video/X-MPEG"));
[email protected]007b3f82013-04-09 08:46:45190 EXPECT_FALSE(MatchesMimeType(std::string(), "video/x-mpeg"));
191 EXPECT_FALSE(MatchesMimeType(std::string(), std::string()));
192 EXPECT_FALSE(MatchesMimeType("video/x-mpeg", std::string()));
[email protected]8effd3f62011-03-25 16:29:07193 EXPECT_FALSE(MatchesMimeType("application/*+xml", "application/xml"));
194 EXPECT_FALSE(MatchesMimeType("application/*+xml",
[email protected]34f40942010-10-04 00:34:04195 "application/html+xmlz"));
[email protected]8effd3f62011-03-25 16:29:07196 EXPECT_FALSE(MatchesMimeType("application/*+xml",
[email protected]34f40942010-10-04 00:34:04197 "applcation/html+xml"));
[email protected]8effd3f62011-03-25 16:29:07198 EXPECT_FALSE(MatchesMimeType("aaa*aaa", "aaaaa"));
[email protected]ad50e8b2012-10-26 03:50:56199
200 EXPECT_TRUE(MatchesMimeType("*", "video/x-mpeg;param=val"));
mtomasz7b54be12015-02-16 06:59:53201 EXPECT_TRUE(MatchesMimeType("*", "Video/X-MPEG;PARAM=VAL"));
[email protected]ad50e8b2012-10-26 03:50:56202 EXPECT_TRUE(MatchesMimeType("video/*", "video/x-mpeg;param=val"));
203 EXPECT_FALSE(MatchesMimeType("video/*;param=val", "video/mpeg"));
mtomasz7b54be12015-02-16 06:59:53204 EXPECT_FALSE(MatchesMimeType("Video/*;PARAM=VAL", "VIDEO/Mpeg"));
[email protected]ad50e8b2012-10-26 03:50:56205 EXPECT_FALSE(MatchesMimeType("video/*;param=val", "video/mpeg;param=other"));
206 EXPECT_TRUE(MatchesMimeType("video/*;param=val", "video/mpeg;param=val"));
mtomasz7b54be12015-02-16 06:59:53207 EXPECT_TRUE(MatchesMimeType("Video/*;PARAM=Val", "VIDEO/Mpeg;Param=Val"));
208 EXPECT_FALSE(MatchesMimeType("Video/*;PARAM=VAL", "VIDEO/Mpeg;Param=Val"));
[email protected]ad50e8b2012-10-26 03:50:56209 EXPECT_TRUE(MatchesMimeType("video/x-mpeg", "video/x-mpeg;param=val"));
210 EXPECT_TRUE(MatchesMimeType("video/x-mpeg;param=val",
211 "video/x-mpeg;param=val"));
212 EXPECT_FALSE(MatchesMimeType("video/x-mpeg;param2=val2",
213 "video/x-mpeg;param=val"));
214 EXPECT_FALSE(MatchesMimeType("video/x-mpeg;param2=val2",
215 "video/x-mpeg;param2=val"));
216 EXPECT_TRUE(MatchesMimeType("video/x-mpeg;param=val",
217 "video/x-mpeg;param=val;param2=val2"));
mtomasz7b54be12015-02-16 06:59:53218 EXPECT_TRUE(MatchesMimeType("Video/X-Mpeg;Param=Val",
219 "VIDEO/X-MPEG;PARAM=Val;PARAM2=val2"));
220 EXPECT_TRUE(MatchesMimeType("Video/X-Mpeg;Param=VAL",
221 "VIDEO/X-MPEG;PARAM=VAL;PARAM2=val2"));
222 EXPECT_FALSE(MatchesMimeType("Video/X-Mpeg;Param=val",
223 "VIDEO/X-MPEG;PARAM=VAL;PARAM2=val2"));
224 EXPECT_FALSE(MatchesMimeType("video/x-mpeg;param=VAL;param2=val2",
225 "video/x-mpeg;param=val;param2=val2"));
[email protected]ad50e8b2012-10-26 03:50:56226 EXPECT_TRUE(MatchesMimeType("video/x-mpeg;param2=val2;param=val",
227 "video/x-mpeg;param=val;param2=val2"));
228 EXPECT_FALSE(MatchesMimeType("video/x-mpeg;param3=val3;param=val",
229 "video/x-mpeg;param=val;param2=val2"));
230 EXPECT_TRUE(MatchesMimeType("video/x-mpeg;param=val ;param2=val2 ",
231 "video/x-mpeg;param=val;param2=val2"));
232
233 EXPECT_TRUE(MatchesMimeType("*/*;param=val", "video/x-mpeg;param=val"));
234 EXPECT_FALSE(MatchesMimeType("*/*;param=val", "video/x-mpeg;param=val2"));
235
236 EXPECT_TRUE(MatchesMimeType("*", "*"));
237 EXPECT_TRUE(MatchesMimeType("*", "*/*"));
238 EXPECT_TRUE(MatchesMimeType("*/*", "*/*"));
239 EXPECT_TRUE(MatchesMimeType("*/*", "*"));
240 EXPECT_TRUE(MatchesMimeType("video/*", "video/*"));
241 EXPECT_FALSE(MatchesMimeType("video/*", "*/*"));
242 EXPECT_FALSE(MatchesMimeType("video/*;param=val", "video/*"));
243 EXPECT_TRUE(MatchesMimeType("video/*;param=val", "video/*;param=val"));
244 EXPECT_FALSE(MatchesMimeType("video/*;param=val", "video/*;param=val2"));
245
246 EXPECT_TRUE(MatchesMimeType("ab*cd", "abxxxcd"));
247 EXPECT_TRUE(MatchesMimeType("ab*cd", "abx/xcd"));
248 EXPECT_TRUE(MatchesMimeType("ab/*cd", "ab/xxxcd"));
initial.commit586acc5fe2008-07-26 22:42:52249}
[email protected]e9696d572009-07-17 23:22:55250
Joel Hockey1864da82021-05-15 02:26:12251TEST(MimeUtilTest, TestParseMimeType) {
252 const struct {
253 std::string type_str;
254 std::string mime_type;
255 base::StringPairs params;
256 } tests[] = {
257 // Simple tests.
258 {"image/jpeg", "image/jpeg"},
259 {"application/octet-stream;foo=bar;name=\"test.jpg\"",
260 "application/octet-stream",
261 {{"foo", "bar"}, {"name", "test.jpg"}}},
262 // Quoted string parsing.
263 {"t/s;name=\"t\\\\est\\\".jpg\"", "t/s", {{"name", "t\\est\".jpg"}}},
264 {"t/s;name=\"test.jpg\"", "t/s", {{"name", "test.jpg"}}},
265 {"t/s;name=\"test;jpg\"", "t/s", {{"name", "test;jpg"}}},
266 // Lenient for no closing quote.
267 {"t/s;name=\"test.jpg", "t/s", {{"name", "test.jpg"}}},
268 {"t/s;name=\"ab\\\"", "t/s", {{"name", "ab\""}}},
269 // Strip whitespace from start/end of mime_type.
270 {" t/s", "t/s"},
271 {"t/s ", "t/s"},
272 {" t/s ", "t/s"},
273 {"t/=", "t/="},
274 // Generally ignore whitespace.
275 {"t/s;a=1;b=2", "t/s", {{"a", "1"}, {"b", "2"}}},
276 {"t/s ;a=1;b=2", "t/s", {{"a", "1"}, {"b", "2"}}},
277 {"t/s; a=1;b=2", "t/s", {{"a", "1"}, {"b", "2"}}},
278 // Special case, include whitespace after param name until equals.
279 {"t/s;a =1;b=2", "t/s", {{"a ", "1"}, {"b", "2"}}},
280 {"t/s;a= 1;b=2", "t/s", {{"a", "1"}, {"b", "2"}}},
281 {"t/s;a=1 ;b=2", "t/s", {{"a", "1"}, {"b", "2"}}},
282 {"t/s;a=1; b=2", "t/s", {{"a", "1"}, {"b", "2"}}},
283 {"t/s; a = 1;b=2", "t/s", {{"a ", "1"}, {"b", "2"}}},
284 // Do not trim whitespace from quoted-string param values.
285 {"t/s;a=\" 1\";b=2", "t/s", {{"a", " 1"}, {"b", "2"}}},
286 {"t/s;a=\"1 \";b=2", "t/s", {{"a", "1 "}, {"b", "2"}}},
287 {"t/s;a=\" 1 \";b=2", "t/s", {{"a", " 1 "}, {"b", "2"}}},
288 // Ignore incomplete params.
289 {"t/s;a", "t/s", {}},
290 {"t/s;a=", "t/s", {}},
291 {"t/s;a=1;", "t/s", {{"a", "1"}}},
292 {"t/s;a=1;b", "t/s", {{"a", "1"}}},
293 {"t/s;a=1;b=", "t/s", {{"a", "1"}}},
294 // Allow empty subtype.
295 {"t/", "t/", {}},
296 {"ts/", "ts/", {}},
297 {"t/;", "t/", {}},
298 {"t/ s", "t/", {}},
299 // Questionable: allow anything as long as there is a slash somewhere.
300 {"/ts", "/ts", {}},
301 {"/s", "/s", {}},
302 {"/", "/", {}},
Joel Hockey1864da82021-05-15 02:26:12303 };
304 for (const auto& test : tests) {
305 std::string mime_type;
306 base::StringPairs params;
307 EXPECT_TRUE(ParseMimeType(test.type_str, &mime_type, &params));
308 EXPECT_EQ(test.mime_type, mime_type);
309 EXPECT_EQ(test.params, params);
310 }
311 for (auto* type_str : {
312 // Must have slash in mime type.
313 "",
314 "ts",
Joel Hockeyf89e0d42021-05-15 02:30:29315 "t / s",
Joel Hockey1864da82021-05-15 02:26:12316 }) {
317 EXPECT_FALSE(ParseMimeType(type_str, nullptr, nullptr));
318 }
319}
320
[email protected]5a6656432014-05-21 23:52:08321TEST(MimeUtilTest, TestParseMimeTypeWithoutParameter) {
[email protected]0b99ae52012-06-06 00:05:59322 std::string nonAscii("application/nonutf8");
Raul Tambre94493c652019-03-11 17:18:35323 EXPECT_TRUE(ParseMimeTypeWithoutParameter(nonAscii, nullptr, nullptr));
Xiaohan Wang2a6845b2022-01-08 04:40:57324#if BUILDFLAG(IS_WIN)
thestig75f87352014-12-03 21:42:27325 nonAscii.append(base::WideToUTF8(L"\u2603"));
[email protected]0b99ae52012-06-06 00:05:59326#else
327 nonAscii.append("\u2603"); // unicode snowman
328#endif
Raul Tambre94493c652019-03-11 17:18:35329 EXPECT_FALSE(ParseMimeTypeWithoutParameter(nonAscii, nullptr, nullptr));
[email protected]0b99ae52012-06-06 00:05:59330
[email protected]5a6656432014-05-21 23:52:08331 std::string top_level_type;
332 std::string subtype;
333 EXPECT_TRUE(ParseMimeTypeWithoutParameter(
334 "application/mime", &top_level_type, &subtype));
335 EXPECT_EQ("application", top_level_type);
336 EXPECT_EQ("mime", subtype);
[email protected]0b99ae52012-06-06 00:05:59337
[email protected]5a6656432014-05-21 23:52:08338 // Various allowed subtype forms.
Raul Tambre94493c652019-03-11 17:18:35339 EXPECT_TRUE(
340 ParseMimeTypeWithoutParameter("application/json", nullptr, nullptr));
341 EXPECT_TRUE(ParseMimeTypeWithoutParameter("application/x-suggestions+json",
342 nullptr, nullptr));
343 EXPECT_TRUE(
344 ParseMimeTypeWithoutParameter("application/+json", nullptr, nullptr));
[email protected]5a6656432014-05-21 23:52:08345
346 // Upper case letters are allowed.
Raul Tambre94493c652019-03-11 17:18:35347 EXPECT_TRUE(ParseMimeTypeWithoutParameter("text/mime", nullptr, nullptr));
348 EXPECT_TRUE(ParseMimeTypeWithoutParameter("TEXT/mime", nullptr, nullptr));
349 EXPECT_TRUE(ParseMimeTypeWithoutParameter("Text/mime", nullptr, nullptr));
350 EXPECT_TRUE(ParseMimeTypeWithoutParameter("TeXt/mime", nullptr, nullptr));
[email protected]5a6656432014-05-21 23:52:08351
352 // Experimental types are also considered to be valid.
Raul Tambre94493c652019-03-11 17:18:35353 EXPECT_TRUE(ParseMimeTypeWithoutParameter("x-video/mime", nullptr, nullptr));
354 EXPECT_TRUE(ParseMimeTypeWithoutParameter("X-Video/mime", nullptr, nullptr));
[email protected]5a6656432014-05-21 23:52:08355
Raul Tambre94493c652019-03-11 17:18:35356 EXPECT_FALSE(ParseMimeTypeWithoutParameter("text", nullptr, nullptr));
357 EXPECT_FALSE(ParseMimeTypeWithoutParameter("text/", nullptr, nullptr));
358 EXPECT_FALSE(ParseMimeTypeWithoutParameter("text/ ", nullptr, nullptr));
359 EXPECT_FALSE(ParseMimeTypeWithoutParameter("te(xt/ ", nullptr, nullptr));
360 EXPECT_FALSE(ParseMimeTypeWithoutParameter("text/()plain", nullptr, nullptr));
[email protected]5a6656432014-05-21 23:52:08361
Raul Tambre94493c652019-03-11 17:18:35362 EXPECT_FALSE(ParseMimeTypeWithoutParameter("x-video", nullptr, nullptr));
363 EXPECT_FALSE(ParseMimeTypeWithoutParameter("x-video/", nullptr, nullptr));
[email protected]5a6656432014-05-21 23:52:08364
Raul Tambre94493c652019-03-11 17:18:35365 EXPECT_FALSE(
366 ParseMimeTypeWithoutParameter("application/a/b/c", nullptr, nullptr));
[email protected]5a6656432014-05-21 23:52:08367
Rob Buis6e0f5222018-11-20 12:01:18368 // Test leading and trailing whitespace
Raul Tambre94493c652019-03-11 17:18:35369 EXPECT_TRUE(ParseMimeTypeWithoutParameter(" text/plain", nullptr, nullptr));
370 EXPECT_TRUE(ParseMimeTypeWithoutParameter("text/plain ", nullptr, nullptr));
371 EXPECT_FALSE(ParseMimeTypeWithoutParameter("text /plain", nullptr, nullptr));
372 EXPECT_FALSE(ParseMimeTypeWithoutParameter("text/ plain ", nullptr, nullptr));
Rob Buis6e0f5222018-11-20 12:01:18373
Raul Tambre94493c652019-03-11 17:18:35374 EXPECT_TRUE(ParseMimeTypeWithoutParameter("\ttext/plain", nullptr, nullptr));
375 EXPECT_TRUE(ParseMimeTypeWithoutParameter("text/plain\t", nullptr, nullptr));
376 EXPECT_FALSE(ParseMimeTypeWithoutParameter("text\t/plain", nullptr, nullptr));
377 EXPECT_FALSE(
378 ParseMimeTypeWithoutParameter("text/\tplain ", nullptr, nullptr));
Rob Buis6e0f5222018-11-20 12:01:18379
Raul Tambre94493c652019-03-11 17:18:35380 EXPECT_TRUE(ParseMimeTypeWithoutParameter("\vtext/plain", nullptr, nullptr));
381 EXPECT_TRUE(ParseMimeTypeWithoutParameter("text/plain\v", nullptr, nullptr));
382 EXPECT_FALSE(ParseMimeTypeWithoutParameter("text\v/plain", nullptr, nullptr));
383 EXPECT_FALSE(
384 ParseMimeTypeWithoutParameter("text/\vplain ", nullptr, nullptr));
Rob Buis6e0f5222018-11-20 12:01:18385
Raul Tambre94493c652019-03-11 17:18:35386 EXPECT_TRUE(ParseMimeTypeWithoutParameter("\rtext/plain", nullptr, nullptr));
387 EXPECT_TRUE(ParseMimeTypeWithoutParameter("text/plain\r", nullptr, nullptr));
388 EXPECT_FALSE(ParseMimeTypeWithoutParameter("text\r/plain", nullptr, nullptr));
389 EXPECT_FALSE(
390 ParseMimeTypeWithoutParameter("text/\rplain ", nullptr, nullptr));
Rob Buis6e0f5222018-11-20 12:01:18391
Raul Tambre94493c652019-03-11 17:18:35392 EXPECT_TRUE(ParseMimeTypeWithoutParameter("\ntext/plain", nullptr, nullptr));
393 EXPECT_TRUE(ParseMimeTypeWithoutParameter("text/plain\n", nullptr, nullptr));
394 EXPECT_FALSE(ParseMimeTypeWithoutParameter("text\n/plain", nullptr, nullptr));
395 EXPECT_FALSE(
396 ParseMimeTypeWithoutParameter("text/\nplain ", nullptr, nullptr));
[email protected]5a6656432014-05-21 23:52:08397}
398
Marcio Caroso57cbb3b722023-03-02 08:39:47399class ExtractMIMETypeTestInvalid : public testing::TestWithParam<std::string> {
400};
401
402INSTANTIATE_TEST_SUITE_P(
403 InvalidMediaTypes,
404 ExtractMIMETypeTestInvalid,
405 testing::Values(
406 // Fails because it doesn't contain '/'.
407 "a",
408 "application",
409 // Space is not HTTP token code point.
410 // https://mimesniff.spec.whatwg.org/#http-token-code-point
411 // U+2003, EM SPACE (UTF-8: E2 80 83).
412 "\xE2\x80\x83text/html",
413 "text\xE2\x80\x83/html",
414 "text / html",
415 "t e x t / h t m l",
416 "text\r\n/\nhtml",
417 "text\n/\nhtml",
418 ", text/html",
419 "; text/html"));
420
421TEST_P(ExtractMIMETypeTestInvalid, MustFail) {
422 // Parsing is expected to fail.
423 EXPECT_EQ(absl::nullopt, net::ExtractMimeTypeFromMediaType(GetParam(), true));
424}
425
426class ExtractMIMETypeTestValid : public testing::TestWithParam<std::string> {};
427
428INSTANTIATE_TEST_SUITE_P(
429 ValidMediaTypes,
430 ExtractMIMETypeTestValid,
431 testing::Values("text/html",
432 "text/html; charset=iso-8859-1",
433 // Quoted charset parameter.
434 "text/html; charset=\"quoted\"",
435 // Multiple parameters.
436 "text/html; charset=x; foo=bar",
437 // OWSes are trimmed.
438 " text/html ",
439 "\ttext/html \t",
440 "text/html ; charset=iso-8859-1"
441 // Non-standard multiple type/subtype listing using a comma
442 // as a separator is accepted.
443 "text/html,text/plain",
444 "text/html , text/plain",
445 "text/html\t,\ttext/plain",
446 "text/html,text/plain;charset=iso-8859-1",
447 "\r\ntext/html\r\n",
448 "text/html;wow",
449 "text/html;;;;;;",
450 "text/html; = = = "));
451
452TEST_P(ExtractMIMETypeTestValid, MustSucceed) {
453 // net::ExtractMIMETypeFromMediaType parses well-formed headers correctly.
454 EXPECT_EQ("text/html",
455 net::ExtractMimeTypeFromMediaType(GetParam(), true).value_or(""));
456}
457
[email protected]5a6656432014-05-21 23:52:08458TEST(MimeUtilTest, TestIsValidTopLevelMimeType) {
459 EXPECT_TRUE(IsValidTopLevelMimeType("application"));
460 EXPECT_TRUE(IsValidTopLevelMimeType("audio"));
461 EXPECT_TRUE(IsValidTopLevelMimeType("example"));
Kenichi Ishibashi9bbe2622021-03-09 02:17:48462 EXPECT_TRUE(IsValidTopLevelMimeType("font"));
[email protected]5a6656432014-05-21 23:52:08463 EXPECT_TRUE(IsValidTopLevelMimeType("image"));
464 EXPECT_TRUE(IsValidTopLevelMimeType("message"));
465 EXPECT_TRUE(IsValidTopLevelMimeType("model"));
466 EXPECT_TRUE(IsValidTopLevelMimeType("multipart"));
467 EXPECT_TRUE(IsValidTopLevelMimeType("text"));
468 EXPECT_TRUE(IsValidTopLevelMimeType("video"));
469
470 EXPECT_TRUE(IsValidTopLevelMimeType("TEXT"));
471 EXPECT_TRUE(IsValidTopLevelMimeType("Text"));
472 EXPECT_TRUE(IsValidTopLevelMimeType("TeXt"));
473
474 EXPECT_FALSE(IsValidTopLevelMimeType("mime"));
475 EXPECT_FALSE(IsValidTopLevelMimeType(""));
476 EXPECT_FALSE(IsValidTopLevelMimeType("/"));
477 EXPECT_FALSE(IsValidTopLevelMimeType(" "));
478
479 EXPECT_TRUE(IsValidTopLevelMimeType("x-video"));
480 EXPECT_TRUE(IsValidTopLevelMimeType("X-video"));
481
482 EXPECT_FALSE(IsValidTopLevelMimeType("x-"));
[email protected]0b99ae52012-06-06 00:05:59483}
484
[email protected]4a66fa0e2012-09-10 06:45:20485TEST(MimeUtilTest, TestGetExtensionsForMimeType) {
486 const struct {
thestig9d3bb0c2015-01-24 00:49:51487 const char* const mime_type;
[email protected]4a66fa0e2012-09-10 06:45:20488 size_t min_expected_size;
thestig9d3bb0c2015-01-24 00:49:51489 const char* const contained_result;
eromanf6ef682612017-01-31 19:12:02490 bool no_matches;
[email protected]4a66fa0e2012-09-10 06:45:20491 } tests[] = {
Raul Tambre94493c652019-03-11 17:18:35492 {"text/plain", 2, "txt"},
493 {"text/pl", 0, nullptr, true},
494 {"*", 0, nullptr},
495 {"", 0, nullptr, true},
496 {"message/*", 1, "eml"},
497 {"MeSsAge/*", 1, "eml"},
498 {"message/", 0, nullptr, true},
Wan-Teh Chang31b25d02020-04-17 18:06:49499 {"image/avif", 1, "avif"},
Raul Tambre94493c652019-03-11 17:18:35500 {"image/bmp", 1, "bmp"},
501 {"video/*", 6, "mp4"},
502 {"video/*", 6, "mpeg"},
503 {"audio/*", 6, "oga"},
504 {"aUDIo/*", 6, "wav"},
[email protected]4a66fa0e2012-09-10 06:45:20505 };
506
eromanf6ef682612017-01-31 19:12:02507 for (const auto& test : tests) {
[email protected]6cdfd7f2013-02-08 20:40:15508 std::vector<base::FilePath::StringType> extensions;
eromanf6ef682612017-01-31 19:12:02509 GetExtensionsForMimeType(test.mime_type, &extensions);
510 ASSERT_LE(test.min_expected_size, extensions.size());
[email protected]4a66fa0e2012-09-10 06:45:20511
eromanf6ef682612017-01-31 19:12:02512 if (test.no_matches)
513 ASSERT_EQ(0u, extensions.size());
[email protected]4a66fa0e2012-09-10 06:45:20514
eromanf6ef682612017-01-31 19:12:02515 if (test.contained_result) {
516 // Convert ASCII to FilePath::StringType.
517 base::FilePath::StringType contained_result(
518 test.contained_result,
519 test.contained_result + strlen(test.contained_result));
520
Jan Wilken Dörrie21f9de72019-06-07 10:41:53521 bool found = base::Contains(extensions, contained_result);
eromanf6ef682612017-01-31 19:12:02522
523 ASSERT_TRUE(found) << "Must find at least the contained result within "
524 << test.mime_type;
[email protected]4a66fa0e2012-09-10 06:45:20525 }
[email protected]4a66fa0e2012-09-10 06:45:20526 }
527}
528
lukaszac644f3712016-01-08 19:35:04529TEST(MimeUtilTest, TestGenerateMimeMultipartBoundary) {
530 std::string boundary1 = GenerateMimeMultipartBoundary();
531 std::string boundary2 = GenerateMimeMultipartBoundary();
532
533 // RFC 1341 says: the boundary parameter [...] consists of 1 to 70 characters.
534 EXPECT_GE(70u, boundary1.size());
535 EXPECT_GE(70u, boundary2.size());
536
537 // RFC 1341 asks to: exercise care to choose a unique boundary.
538 EXPECT_NE(boundary1, boundary2);
539 ASSERT_LE(16u, boundary1.size());
540 ASSERT_LE(16u, boundary2.size());
541
542 // Expect that we don't pick '\0' character from the array/string
543 // where we take the characters from.
544 EXPECT_EQ(std::string::npos, boundary1.find('\0'));
545 EXPECT_EQ(std::string::npos, boundary2.find('\0'));
546
547 // Asserts below are not RFC 1341 requirements, but are here
548 // to improve readability of generated MIME documents and to
549 // try to preserve some aspects of the old boundary generation code.
550 EXPECT_EQ("--", boundary1.substr(0, 2));
551 EXPECT_EQ("--", boundary2.substr(0, 2));
552 EXPECT_NE(std::string::npos, boundary1.find("MultipartBoundary"));
553 EXPECT_NE(std::string::npos, boundary2.find("MultipartBoundary"));
554 EXPECT_EQ("--", boundary1.substr(boundary1.size() - 2, 2));
555 EXPECT_EQ("--", boundary2.substr(boundary2.size() - 2, 2));
556}
[email protected]3b455502012-12-11 18:22:58557
[email protected]591d361a2013-05-17 11:38:06558TEST(MimeUtilTest, TestAddMultipartValueForUpload) {
thestig9d3bb0c2015-01-24 00:49:51559 const char ref_output[] =
560 "--boundary\r\nContent-Disposition: form-data;"
561 " name=\"value name\"\r\nContent-Type: content type"
562 "\r\n\r\nvalue\r\n"
563 "--boundary\r\nContent-Disposition: form-data;"
564 " name=\"value name\"\r\n\r\nvalue\r\n"
565 "--boundary--\r\n";
[email protected]591d361a2013-05-17 11:38:06566 std::string post_data;
567 AddMultipartValueForUpload("value name", "value", "boundary",
568 "content type", &post_data);
569 AddMultipartValueForUpload("value name", "value", "boundary",
570 "", &post_data);
571 AddMultipartFinalDelimiterForUpload("boundary", &post_data);
572 EXPECT_STREQ(ref_output, post_data.c_str());
573}
574
Ethan Xuc4740ea2018-11-28 21:31:20575TEST(MimeUtilTest, TestAddMultipartValueForUploadWithFileName) {
576 const char ref_output[] =
577 "--boundary\r\nContent-Disposition: form-data;"
578 " name=\"value name\"; filename=\"file name\"\r\nContent-Type: content "
579 "type"
580 "\r\n\r\nvalue\r\n"
581 "--boundary\r\nContent-Disposition: form-data;"
582 " name=\"value name\"; filename=\"file name\"\r\n\r\nvalue\r\n"
583 "--boundary--\r\n";
584 std::string post_data;
585 AddMultipartValueForUploadWithFileName("value name", "file name", "value",
586 "boundary", "content type",
587 &post_data);
588 AddMultipartValueForUploadWithFileName("value name", "file name", "value",
589 "boundary", "", &post_data);
590 AddMultipartFinalDelimiterForUpload("boundary", &post_data);
591 EXPECT_STREQ(ref_output, post_data.c_str());
592}
[email protected]8effd3f62011-03-25 16:29:07593} // namespace net