mime_sniffer_unittest.cc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. // Copyright (c) 2011 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/base/mime_sniffer.h"
  5. #include "build/build_config.h"
  6. #include "testing/gtest/include/gtest/gtest.h"
  7. #include "url/gurl.h"
  8. #include "url/url_constants.h"
  9. namespace net {
  10. namespace {
  11. using ::testing::Range;
  12. using ::testing::Values;
  13. using ::net::SniffMimeType; // It is shadowed by SniffMimeType(), below.
  14. // Turn |str|, a constant string with one or more embedded NULs, along with
  15. // a NUL terminator, into an std::string() containing just that data.
  16. // Turn |str|, a string with one or more embedded NULs, into an std::string()
  17. template <size_t N>
  18. std::string MakeConstantString(const char (&str)[N]) {
  19. return std::string(str, N - 1);
  20. }
  21. static std::string SniffMimeType(base::StringPiece content,
  22. const std::string& url,
  23. const std::string& mime_type_hint) {
  24. std::string mime_type;
  25. SniffMimeType(content, GURL(url), mime_type_hint,
  26. ForceSniffFileUrlsForHtml::kDisabled, &mime_type);
  27. return mime_type;
  28. }
  29. TEST(MimeSnifferTest, SniffableSchemes) {
  30. struct {
  31. const char* scheme;
  32. bool sniffable;
  33. } kTestCases[] = {
  34. {url::kAboutScheme, false},
  35. {url::kBlobScheme, false},
  36. #if BUILDFLAG(IS_ANDROID)
  37. {url::kContentScheme, true},
  38. #else
  39. {url::kContentScheme, false},
  40. #endif
  41. {url::kContentIDScheme, false},
  42. {url::kDataScheme, false},
  43. {url::kFileScheme, true},
  44. {url::kFileSystemScheme, true},
  45. {url::kFtpScheme, false},
  46. {url::kHttpScheme, true},
  47. {url::kHttpsScheme, true},
  48. {url::kJavaScriptScheme, false},
  49. {url::kMailToScheme, false},
  50. {url::kWsScheme, false},
  51. {url::kWssScheme, false}
  52. };
  53. for (const auto test_case : kTestCases) {
  54. GURL url(std::string(test_case.scheme) + "://host/path/whatever");
  55. EXPECT_EQ(test_case.sniffable, ShouldSniffMimeType(url, ""));
  56. }
  57. }
  58. TEST(MimeSnifferTest, BoundaryConditionsTest) {
  59. std::string mime_type;
  60. std::string type_hint;
  61. char buf[] = {
  62. 'd', '\x1f', '\xFF'
  63. };
  64. GURL url;
  65. SniffMimeType(base::StringPiece(), url, type_hint,
  66. ForceSniffFileUrlsForHtml::kDisabled, &mime_type);
  67. EXPECT_EQ("text/plain", mime_type);
  68. SniffMimeType(base::StringPiece(buf, 1), url, type_hint,
  69. ForceSniffFileUrlsForHtml::kDisabled, &mime_type);
  70. EXPECT_EQ("text/plain", mime_type);
  71. SniffMimeType(base::StringPiece(buf, 2), url, type_hint,
  72. ForceSniffFileUrlsForHtml::kDisabled, &mime_type);
  73. EXPECT_EQ("application/octet-stream", mime_type);
  74. }
  75. TEST(MimeSnifferTest, BasicSniffingTest) {
  76. EXPECT_EQ("text/html",
  77. SniffMimeType(MakeConstantString("<!DOCTYPE html PUBLIC"),
  78. "http://www.example.com/", ""));
  79. EXPECT_EQ("application/octet-stream",
  80. SniffMimeType(MakeConstantString("<HtMl><Body></body></htMl>"),
  81. "http://www.example.com/foo.gif",
  82. "application/octet-stream"));
  83. EXPECT_EQ("image/gif",
  84. SniffMimeType(MakeConstantString("GIF89a\x1F\x83\x94"),
  85. "http://www.example.com/foo", "text/plain"));
  86. EXPECT_EQ("application/octet-stream",
  87. SniffMimeType(MakeConstantString("Gif87a\x1F\x83\x94"),
  88. "http://www.example.com/foo?param=tt.gif", ""));
  89. EXPECT_EQ("text/plain",
  90. SniffMimeType(MakeConstantString("%!PS-Adobe-3.0"),
  91. "http://www.example.com/foo", "text/plain"));
  92. EXPECT_EQ(
  93. "application/octet-stream",
  94. SniffMimeType(MakeConstantString("\x89"
  95. "PNG\x0D\x0A\x1A\x0A"),
  96. "http://www.example.com/foo", "application/octet-stream"));
  97. EXPECT_EQ("image/jpeg",
  98. SniffMimeType(MakeConstantString("\xFF\xD8\xFF\x23\x49\xAF"),
  99. "http://www.example.com/foo", ""));
  100. }
  101. TEST(MimeSnifferTest, ChromeExtensionsTest) {
  102. // schemes
  103. EXPECT_EQ("application/x-chrome-extension",
  104. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  105. "http://www.example.com/foo.crx", ""));
  106. EXPECT_EQ("application/x-chrome-extension",
  107. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  108. "https://www.example.com/foo.crx", ""));
  109. EXPECT_EQ("application/x-chrome-extension",
  110. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  111. "ftp://www.example.com/foo.crx", ""));
  112. // some other mimetypes that should get converted
  113. EXPECT_EQ("application/x-chrome-extension",
  114. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  115. "http://www.example.com/foo.crx", "text/plain"));
  116. EXPECT_EQ("application/x-chrome-extension",
  117. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  118. "http://www.example.com/foo.crx",
  119. "application/octet-stream"));
  120. // success edge cases
  121. EXPECT_EQ("application/x-chrome-extension",
  122. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  123. "http://www.example.com/foo.crx?query=string", ""));
  124. EXPECT_EQ("application/x-chrome-extension",
  125. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  126. "http://www.example.com/foo..crx", ""));
  127. EXPECT_EQ("application/x-chrome-extension",
  128. SniffMimeType(MakeConstantString("Cr24\x03\x00\x00\x00"),
  129. "http://www.example.com/foo..crx", ""));
  130. // wrong file extension
  131. EXPECT_EQ("application/octet-stream",
  132. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  133. "http://www.example.com/foo.bin", ""));
  134. EXPECT_EQ("application/octet-stream",
  135. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  136. "http://www.example.com/foo.bin?monkey", ""));
  137. EXPECT_EQ("application/octet-stream",
  138. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  139. "invalid-url", ""));
  140. EXPECT_EQ("application/octet-stream",
  141. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  142. "http://www.example.com", ""));
  143. EXPECT_EQ("application/octet-stream",
  144. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  145. "http://www.example.com/", ""));
  146. EXPECT_EQ("application/octet-stream",
  147. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  148. "http://www.example.com/foo", ""));
  149. EXPECT_EQ("application/octet-stream",
  150. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  151. "http://www.example.com/foocrx", ""));
  152. EXPECT_EQ("application/octet-stream",
  153. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x00"),
  154. "http://www.example.com/foo.crx.blech", ""));
  155. // wrong magic
  156. EXPECT_EQ("application/octet-stream",
  157. SniffMimeType(MakeConstantString("Cr24\x02\x00\x00\x01"),
  158. "http://www.example.com/foo.crx?monkey", ""));
  159. EXPECT_EQ("application/octet-stream",
  160. SniffMimeType(MakeConstantString("PADDING_Cr24\x02\x00\x00\x00"),
  161. "http://www.example.com/foo.crx?monkey", ""));
  162. }
  163. TEST(MimeSnifferTest, MozillaCompatibleTest) {
  164. EXPECT_EQ("text/html", SniffMimeType(MakeConstantString(" \n <hTmL>\n <hea"),
  165. "http://www.example.com/", ""));
  166. EXPECT_EQ("text/plain",
  167. SniffMimeType(MakeConstantString(" \n <hTmL>\n <hea"),
  168. "http://www.example.com/", "text/plain"));
  169. EXPECT_EQ("image/bmp", SniffMimeType(MakeConstantString("BMjlakdsfk"),
  170. "http://www.example.com/foo", ""));
  171. EXPECT_EQ("application/octet-stream",
  172. SniffMimeType(MakeConstantString("\x00\x00\x30\x00"),
  173. "http://www.example.com/favicon.ico", ""));
  174. EXPECT_EQ("text/plain", SniffMimeType(MakeConstantString("#!/bin/sh\nls /\n"),
  175. "http://www.example.com/foo", ""));
  176. EXPECT_EQ("text/plain",
  177. SniffMimeType(MakeConstantString("From: Fred\nTo: Bob\n\nHi\n.\n"),
  178. "http://www.example.com/foo", ""));
  179. EXPECT_EQ("text/xml",
  180. SniffMimeType(MakeConstantString(
  181. "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"),
  182. "http://www.example.com/foo", ""));
  183. EXPECT_EQ(
  184. "application/octet-stream",
  185. SniffMimeType(
  186. MakeConstantString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"),
  187. "http://www.example.com/foo", "application/octet-stream"));
  188. }
  189. TEST(MimeSnifferTest, DontAllowPrivilegeEscalationTest) {
  190. EXPECT_EQ(
  191. "image/gif",
  192. SniffMimeType(MakeConstantString("GIF87a\n<html>\n<body>"
  193. "<script>alert('haxorzed');\n</script>"
  194. "</body></html>\n"),
  195. "http://www.example.com/foo", ""));
  196. EXPECT_EQ(
  197. "image/gif",
  198. SniffMimeType(MakeConstantString("GIF87a\n<html>\n<body>"
  199. "<script>alert('haxorzed');\n</script>"
  200. "</body></html>\n"),
  201. "http://www.example.com/foo?q=ttt.html", ""));
  202. EXPECT_EQ(
  203. "image/gif",
  204. SniffMimeType(MakeConstantString("GIF87a\n<html>\n<body>"
  205. "<script>alert('haxorzed');\n</script>"
  206. "</body></html>\n"),
  207. "http://www.example.com/foo#ttt.html", ""));
  208. EXPECT_EQ(
  209. "text/plain",
  210. SniffMimeType(MakeConstantString("a\n<html>\n<body>"
  211. "<script>alert('haxorzed');\n</script>"
  212. "</body></html>\n"),
  213. "http://www.example.com/foo", ""));
  214. EXPECT_EQ(
  215. "text/plain",
  216. SniffMimeType(MakeConstantString("a\n<html>\n<body>"
  217. "<script>alert('haxorzed');\n</script>"
  218. "</body></html>\n"),
  219. "http://www.example.com/foo?q=ttt.html", ""));
  220. EXPECT_EQ(
  221. "text/plain",
  222. SniffMimeType(MakeConstantString("a\n<html>\n<body>"
  223. "<script>alert('haxorzed');\n</script>"
  224. "</body></html>\n"),
  225. "http://www.example.com/foo#ttt.html", ""));
  226. EXPECT_EQ(
  227. "text/plain",
  228. SniffMimeType(MakeConstantString("a\n<html>\n<body>"
  229. "<script>alert('haxorzed');\n</script>"
  230. "</body></html>\n"),
  231. "http://www.example.com/foo.html", ""));
  232. }
  233. TEST(MimeSnifferTest, SniffFilesAsHtml) {
  234. const std::string kContent = "<html><body>text</body></html>";
  235. const GURL kUrl("file:///C/test.unusualextension");
  236. std::string mime_type;
  237. SniffMimeType(kContent, kUrl, "" /* type_hint */,
  238. ForceSniffFileUrlsForHtml::kDisabled, &mime_type);
  239. EXPECT_EQ("text/plain", mime_type);
  240. SniffMimeType(kContent, kUrl, "" /* type_hint */,
  241. ForceSniffFileUrlsForHtml::kEnabled, &mime_type);
  242. EXPECT_EQ("text/html", mime_type);
  243. }
  244. TEST(MimeSnifferTest, UnicodeTest) {
  245. EXPECT_EQ("text/plain", SniffMimeType(MakeConstantString("\xEF\xBB\xBF"
  246. "Hi there"),
  247. "http://www.example.com/foo", ""));
  248. EXPECT_EQ(
  249. "text/plain",
  250. SniffMimeType(MakeConstantString("\xEF\xBB\xBF\xED\x7A\xAD\x7A\x0D\x79"),
  251. "http://www.example.com/foo", ""));
  252. EXPECT_EQ(
  253. "text/plain",
  254. SniffMimeType(MakeConstantString(
  255. "\xFE\xFF\xD0\xA5\xD0\xBE\xD0\xBB\xD1\x83\xD0\xB9"),
  256. "http://www.example.com/foo", ""));
  257. EXPECT_EQ("text/plain",
  258. SniffMimeType(
  259. MakeConstantString(
  260. "\xFE\xFF\x00\x41\x00\x20\xD8\x00\xDC\x00\xD8\x00\xDC\x01"),
  261. "http://www.example.com/foo", ""));
  262. }
  263. TEST(MimeSnifferTest, FlashTest) {
  264. EXPECT_EQ("application/octet-stream",
  265. SniffMimeType(MakeConstantString("CWSdd\x00\xB3"),
  266. "http://www.example.com/foo", ""));
  267. EXPECT_EQ("application/octet-stream",
  268. SniffMimeType(MakeConstantString("FLVjdkl*(#)0sdj\x00"),
  269. "http://www.example.com/foo?q=ttt.swf", ""));
  270. EXPECT_EQ("application/octet-stream",
  271. SniffMimeType(MakeConstantString("FWS3$9\r\b\x00"),
  272. "http://www.example.com/foo#ttt.swf", ""));
  273. EXPECT_EQ("text/plain", SniffMimeType(MakeConstantString("FLVjdkl*(#)0sdj"),
  274. "http://www.example.com/foo.swf", ""));
  275. EXPECT_EQ("application/octet-stream",
  276. SniffMimeType(MakeConstantString("FLVjdkl*(#)0s\x01dj"),
  277. "http://www.example.com/foo/bar.swf", ""));
  278. EXPECT_EQ("application/octet-stream",
  279. SniffMimeType(MakeConstantString("FWS3$9\r\b\x1A"),
  280. "http://www.example.com/foo.swf?clickTAG=http://"
  281. "www.adnetwork.com/bar",
  282. ""));
  283. EXPECT_EQ("application/octet-stream",
  284. SniffMimeType(MakeConstantString("FWS3$9\r\x1C\b"),
  285. "http://www.example.com/foo.swf?clickTAG=http://"
  286. "www.adnetwork.com/bar",
  287. "text/plain"));
  288. }
  289. TEST(MimeSnifferTest, XMLTest) {
  290. // An easy feed to identify.
  291. EXPECT_EQ("application/atom+xml",
  292. SniffMimeType("<?xml?><feed", "", "text/xml"));
  293. // Don't sniff out of plain text.
  294. EXPECT_EQ("text/plain", SniffMimeType("<?xml?><feed", "", "text/plain"));
  295. // Simple RSS.
  296. EXPECT_EQ("application/rss+xml",
  297. SniffMimeType("<?xml version='1.0'?>\r\n<rss", "", "text/xml"));
  298. // The top of CNN's RSS feed, which we'd like to recognize as RSS.
  299. static const char kCNNRSS[] =
  300. "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  301. "<?xml-stylesheet href=\"http://rss.cnn.com/~d/styles/rss2full.xsl\" "
  302. "type=\"text/xsl\" media=\"screen\"?>"
  303. "<?xml-stylesheet href=\"http://rss.cnn.com/~d/styles/itemcontent.css\" "
  304. "type=\"text/css\" media=\"screen\"?>"
  305. "<rss xmlns:feedburner=\"http://rssnamespace.org/feedburner/ext/1.0\" "
  306. "version=\"2.0\">";
  307. // CNN's RSS
  308. EXPECT_EQ("application/rss+xml", SniffMimeType(kCNNRSS, "", "text/xml"));
  309. EXPECT_EQ("text/plain", SniffMimeType(kCNNRSS, "", "text/plain"));
  310. // Don't sniff random XML as something different.
  311. EXPECT_EQ("text/xml", SniffMimeType("<?xml?><notafeed", "", "text/xml"));
  312. // Don't sniff random plain-text as something different.
  313. EXPECT_EQ("text/plain", SniffMimeType("<?xml?><notafeed", "", "text/plain"));
  314. // We never upgrade to application/xhtml+xml.
  315. EXPECT_EQ("text/xml",
  316. SniffMimeType("<html xmlns=\"http://www.w3.org/1999/xhtml\">", "",
  317. "text/xml"));
  318. EXPECT_EQ("application/xml",
  319. SniffMimeType("<html xmlns=\"http://www.w3.org/1999/xhtml\">", "",
  320. "application/xml"));
  321. EXPECT_EQ("text/plain",
  322. SniffMimeType("<html xmlns=\"http://www.w3.org/1999/xhtml\">", "",
  323. "text/plain"));
  324. EXPECT_EQ("application/rss+xml",
  325. SniffMimeType("<html xmlns=\"http://www.w3.org/1999/xhtml\">", "",
  326. "application/rss+xml"));
  327. EXPECT_EQ("text/xml", SniffMimeType("<html><head>", "", "text/xml"));
  328. EXPECT_EQ("text/xml",
  329. SniffMimeType("<foo><rss "
  330. "xmlns:feedburner=\"http://rssnamespace.org/"
  331. "feedburner/ext/1.0\" version=\"2.0\">",
  332. "", "text/xml"));
  333. }
  334. // Test content which is >= 1024 bytes, and includes no open angle bracket.
  335. // http://code.google.com/p/chromium/issues/detail?id=3521
  336. TEST(MimeSnifferTest, XMLTestLargeNoAngledBracket) {
  337. // Make a large input, with 1024 bytes of "x".
  338. std::string content;
  339. content.resize(1024);
  340. std::fill(content.begin(), content.end(), 'x');
  341. // content.size() >= 1024 so the sniff is unambiguous.
  342. std::string mime_type;
  343. EXPECT_TRUE(SniffMimeType(content, GURL(), "text/xml",
  344. ForceSniffFileUrlsForHtml::kDisabled, &mime_type));
  345. EXPECT_EQ("text/xml", mime_type);
  346. }
  347. // Test content which is >= 1024 bytes, and includes a binary looking byte.
  348. // http://code.google.com/p/chromium/issues/detail?id=15314
  349. TEST(MimeSnifferTest, LooksBinary) {
  350. // Make a large input, with 1024 bytes of "x" and 1 byte of 0x01.
  351. std::string content;
  352. content.resize(1024);
  353. std::fill(content.begin(), content.end(), 'x');
  354. content[1000] = 0x01;
  355. // content.size() >= 1024 so the sniff is unambiguous.
  356. std::string mime_type;
  357. EXPECT_TRUE(SniffMimeType(content, GURL(), "text/plain",
  358. ForceSniffFileUrlsForHtml::kDisabled, &mime_type));
  359. EXPECT_EQ("application/octet-stream", mime_type);
  360. }
  361. TEST(MimeSnifferTest, OfficeTest) {
  362. // Check for URLs incorrectly reported as Microsoft Office files.
  363. EXPECT_EQ(
  364. "application/octet-stream",
  365. SniffMimeType(MakeConstantString("Hi there"),
  366. "http://www.example.com/foo.doc", "application/msword"));
  367. EXPECT_EQ("application/octet-stream",
  368. SniffMimeType(MakeConstantString("Hi there"),
  369. "http://www.example.com/foo.xls",
  370. "application/vnd.ms-excel"));
  371. EXPECT_EQ("application/octet-stream",
  372. SniffMimeType(MakeConstantString("Hi there"),
  373. "http://www.example.com/foo.ppt",
  374. "application/vnd.ms-powerpoint"));
  375. // Check for Microsoft Office files incorrectly reported as text.
  376. EXPECT_EQ(
  377. "application/msword",
  378. SniffMimeType(MakeConstantString("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
  379. "Hi there"),
  380. "http://www.example.com/foo.doc", "text/plain"));
  381. EXPECT_EQ(
  382. "application/vnd.openxmlformats-officedocument."
  383. "wordprocessingml.document",
  384. SniffMimeType(MakeConstantString(
  385. "PK\x03\x04"
  386. "Hi there"),
  387. "http://www.example.com/foo.doc", "text/plain"));
  388. EXPECT_EQ(
  389. "application/vnd.ms-excel",
  390. SniffMimeType(MakeConstantString("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
  391. "Hi there"),
  392. "http://www.example.com/foo.xls", "text/plain"));
  393. EXPECT_EQ(
  394. "application/vnd.openxmlformats-officedocument."
  395. "spreadsheetml.sheet",
  396. SniffMimeType(MakeConstantString("PK\x03\x04"
  397. "Hi there"),
  398. "http://www.example.com/foo.xls", "text/plain"));
  399. EXPECT_EQ(
  400. "application/vnd.ms-powerpoint",
  401. SniffMimeType(MakeConstantString("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
  402. "Hi there"),
  403. "http://www.example.com/foo.ppt", "text/plain"));
  404. EXPECT_EQ(
  405. "application/vnd.openxmlformats-officedocument."
  406. "presentationml.presentation",
  407. SniffMimeType(MakeConstantString("PK\x03\x04"
  408. "Hi there"),
  409. "http://www.example.com/foo.ppt", "text/plain"));
  410. }
  411. TEST(MimeSnifferTest, AudioVideoTest) {
  412. std::string mime_type;
  413. const char kOggTestData[] = "OggS\x00";
  414. EXPECT_TRUE(SniffMimeTypeFromLocalData(
  415. base::StringPiece(kOggTestData, sizeof(kOggTestData) - 1), &mime_type));
  416. EXPECT_EQ("audio/ogg", mime_type);
  417. mime_type.clear();
  418. // Check ogg header requires the terminal '\0' to be sniffed.
  419. EXPECT_FALSE(SniffMimeTypeFromLocalData(
  420. base::StringPiece(kOggTestData, sizeof(kOggTestData) - 2), &mime_type));
  421. EXPECT_EQ("", mime_type);
  422. mime_type.clear();
  423. const char kFlacTestData[] =
  424. "fLaC\x00\x00\x00\x22\x12\x00\x12\x00\x00\x00\x00\x00";
  425. EXPECT_TRUE(SniffMimeTypeFromLocalData(
  426. base::StringPiece(kFlacTestData, sizeof(kFlacTestData) - 1), &mime_type));
  427. EXPECT_EQ("audio/x-flac", mime_type);
  428. mime_type.clear();
  429. const char kWMATestData[] =
  430. "\x30\x26\xb2\x75\x8e\x66\xcf\x11\xa6\xd9\x00\xaa\x00\x62\xce\x6c";
  431. EXPECT_TRUE(SniffMimeTypeFromLocalData(
  432. base::StringPiece(kWMATestData, sizeof(kWMATestData) - 1), &mime_type));
  433. EXPECT_EQ("video/x-ms-asf", mime_type);
  434. mime_type.clear();
  435. // mp4a, m4b, m4p, and alac extension files which share the same container
  436. // format.
  437. const char kMP4TestData[] =
  438. "\x00\x00\x00\x20\x66\x74\x79\x70\x4d\x34\x41\x20\x00\x00\x00\x00";
  439. EXPECT_TRUE(SniffMimeTypeFromLocalData(
  440. base::StringPiece(kMP4TestData, sizeof(kMP4TestData) - 1), &mime_type));
  441. EXPECT_EQ("video/mp4", mime_type);
  442. mime_type.clear();
  443. const char kAACTestData[] =
  444. "\xff\xf1\x50\x80\x02\x20\xb0\x23\x0a\x83\x20\x7d\x61\x90\x3e\xb1";
  445. EXPECT_TRUE(SniffMimeTypeFromLocalData(
  446. base::StringPiece(kAACTestData, sizeof(kAACTestData) - 1), &mime_type));
  447. EXPECT_EQ("audio/mpeg", mime_type);
  448. mime_type.clear();
  449. const char kAMRTestData[] =
  450. "\x23\x21\x41\x4d\x52\x0a\x3c\x53\x0a\x7c\xe8\xb8\x41\xa5\x80\xca";
  451. EXPECT_TRUE(SniffMimeTypeFromLocalData(
  452. base::StringPiece(kAMRTestData, sizeof(kAMRTestData) - 1), &mime_type));
  453. EXPECT_EQ("audio/amr", mime_type);
  454. mime_type.clear();
  455. }
  456. TEST(MimeSnifferTest, ImageTest) {
  457. std::string mime_type;
  458. const char kWebPSimpleFormat[] = "RIFF\xee\x81\x00\x00WEBPVP8 ";
  459. EXPECT_TRUE(SniffMimeTypeFromLocalData(
  460. base::StringPiece(kWebPSimpleFormat, sizeof(kWebPSimpleFormat) - 1),
  461. &mime_type));
  462. EXPECT_EQ("image/webp", mime_type);
  463. mime_type.clear();
  464. const char kWebPLosslessFormat[] = "RIFF\xee\x81\x00\x00WEBPVP8L";
  465. EXPECT_TRUE(SniffMimeTypeFromLocalData(
  466. base::StringPiece(kWebPLosslessFormat, sizeof(kWebPLosslessFormat) - 1),
  467. &mime_type));
  468. EXPECT_EQ("image/webp", mime_type);
  469. mime_type.clear();
  470. const char kWebPExtendedFormat[] = "RIFF\xee\x81\x00\x00WEBPVP8X";
  471. EXPECT_TRUE(SniffMimeTypeFromLocalData(
  472. base::StringPiece(kWebPExtendedFormat, sizeof(kWebPExtendedFormat) - 1),
  473. &mime_type));
  474. EXPECT_EQ("image/webp", mime_type);
  475. mime_type.clear();
  476. }
  477. // The tests need char parameters, but the ranges to test include 0xFF, and some
  478. // platforms have signed chars and are noisy about it. Using an int parameter
  479. // and casting it to char inside the test case solves both these problems.
  480. class MimeSnifferBinaryTest : public ::testing::TestWithParam<int> {};
  481. // From https://mimesniff.spec.whatwg.org/#binary-data-byte :
  482. // A binary data byte is a byte in the range 0x00 to 0x08 (NUL to BS), the byte
  483. // 0x0B (VT), a byte in the range 0x0E to 0x1A (SO to SUB), or a byte in the
  484. // range 0x1C to 0x1F (FS to US).
  485. TEST_P(MimeSnifferBinaryTest, IsBinaryControlCode) {
  486. std::string param(1, static_cast<char>(GetParam()));
  487. EXPECT_TRUE(LooksLikeBinary(param));
  488. }
  489. // ::testing::Range(a, b) tests an open-ended range, ie. "b" is not included.
  490. INSTANTIATE_TEST_SUITE_P(MimeSnifferBinaryTestRange1,
  491. MimeSnifferBinaryTest,
  492. Range(0x00, 0x09));
  493. INSTANTIATE_TEST_SUITE_P(MimeSnifferBinaryTestByte0x0B,
  494. MimeSnifferBinaryTest,
  495. Values(0x0B));
  496. INSTANTIATE_TEST_SUITE_P(MimeSnifferBinaryTestRange2,
  497. MimeSnifferBinaryTest,
  498. Range(0x0E, 0x1B));
  499. INSTANTIATE_TEST_SUITE_P(MimeSnifferBinaryTestRange3,
  500. MimeSnifferBinaryTest,
  501. Range(0x1C, 0x20));
  502. class MimeSnifferPlainTextTest : public ::testing::TestWithParam<int> {};
  503. TEST_P(MimeSnifferPlainTextTest, NotBinaryControlCode) {
  504. std::string param(1, static_cast<char>(GetParam()));
  505. EXPECT_FALSE(LooksLikeBinary(param));
  506. }
  507. INSTANTIATE_TEST_SUITE_P(MimeSnifferPlainTextTestPlainTextControlCodes,
  508. MimeSnifferPlainTextTest,
  509. Values(0x09, 0x0A, 0x0C, 0x0D, 0x1B));
  510. INSTANTIATE_TEST_SUITE_P(MimeSnifferPlainTextTestNotControlCodeRange,
  511. MimeSnifferPlainTextTest,
  512. Range(0x20, 0x100));
  513. class MimeSnifferControlCodesEdgeCaseTest
  514. : public ::testing::TestWithParam<const char*> {};
  515. TEST_P(MimeSnifferControlCodesEdgeCaseTest, EdgeCase) {
  516. EXPECT_TRUE(LooksLikeBinary(GetParam()));
  517. }
  518. INSTANTIATE_TEST_SUITE_P(MimeSnifferControlCodesEdgeCaseTest,
  519. MimeSnifferControlCodesEdgeCaseTest,
  520. Values("\x01__", // first byte is binary
  521. "__\x03", // last byte is binary
  522. "_\x02_" // a byte in the middle is binary
  523. ));
  524. } // namespace
  525. } // namespace net