summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/base/mime_sniffer.cc44
-rw-r--r--net/base/mime_sniffer_unittest.cc64
2 files changed, 107 insertions, 1 deletions
diff --git a/net/base/mime_sniffer.cc b/net/base/mime_sniffer.cc
index 0a8bc57..07feb33 100644
--- a/net/base/mime_sniffer.cc
+++ b/net/base/mime_sniffer.cc
@@ -256,7 +256,7 @@ static bool CheckForMagicNumbers(const char* content, size_t size,
Histogram* counter, std::string* result) {
for (size_t i = 0; i < magic_len; ++i) {
if (MatchMagicNumber(content, size, &(magic[i]), result)) {
- counter->Add(static_cast<int>(i));
+ if (counter) counter->Add(static_cast<int>(i));
return true;
}
}
@@ -438,6 +438,43 @@ static bool IsUnknownMimeType(const std::string& mime_type) {
return false;
}
+// Sniff a crx (chrome extension) file.
+static bool SniffCRX(const char* content, size_t content_size, const GURL& url,
+ const std::string& type_hint, std::string* result) {
+ static SnifferHistogram counter("mime_sniffer.kSniffCRX", 3);
+
+ // Technically, the crx magic number is just Cr24, but the bytes after that
+ // are a version number which changes infrequently. Including it in the
+ // sniffing gives us less room for error. If the version number ever changes,
+ // we can just add an entry to this list.
+ //
+ // TODO(aa): If we ever have another magic number, we'll want to pass a
+ // histogram into CheckForMagicNumbers(), below, to see which one matched.
+ const struct MagicNumber kCRXMagicNumbers[] = {
+ MAGIC_NUMBER("application/x-chrome-extension", "Cr24\x02\x00\x00\x00")
+ };
+
+ // Only consider files that have the extension ".crx".
+ const char kCRXExtension[] = ".crx";
+ const int kExtensionLength = arraysize(kCRXExtension) - 1; // ignore null
+ if (url.path().rfind(kCRXExtension, std::string::npos, kExtensionLength) ==
+ url.path().size() - kExtensionLength) {
+ counter.Add(1);
+ } else {
+ return false;
+ }
+
+ if (CheckForMagicNumbers(content, content_size,
+ kCRXMagicNumbers, arraysize(kCRXMagicNumbers),
+ NULL, result)) {
+ counter.Add(2);
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
bool ShouldSniffMimeType(const GURL& url, const std::string& mime_type) {
static SnifferHistogram should_sniff_counter(
"mime_sniffer.ShouldSniffMimeType2", 3);
@@ -535,6 +572,11 @@ bool SniffMimeType(const char* content, size_t content_size,
return content_size >= kMaxBytesToSniff;
}
+ // CRX files (chrome extensions) have a special sniffing algorithm. It is
+ // tighter than the others because we don't have to match legacy behavior.
+ if (SniffCRX(content, content_size, url, type_hint, result))
+ return true;
+
// Now we look in our large table of magic numbers to see if we can find
// anything that matches the content.
if (SniffForMagicNumbers(content, content_size, result))
diff --git a/net/base/mime_sniffer_unittest.cc b/net/base/mime_sniffer_unittest.cc
index 96eb441..ed1634c 100644
--- a/net/base/mime_sniffer_unittest.cc
+++ b/net/base/mime_sniffer_unittest.cc
@@ -90,6 +90,70 @@ TEST(MimeSnifferTest, BasicSniffingTest) {
TestArray(tests, arraysize(tests));
}
+TEST(MimeSnifferTest, ChromeExtensionsTest) {
+ SnifferTest tests[] = {
+ // schemes
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "http://www.example.com/foo.crx",
+ "", "application/x-chrome-extension" },
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "https://www.example.com/foo.crx",
+ "", "application/x-chrome-extension" },
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "ftp://www.example.com/foo.crx",
+ "", "application/x-chrome-extension" },
+
+ // some other mimetypes that should get converted
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "http://www.example.com/foo.crx",
+ "text/plain", "application/x-chrome-extension" },
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "http://www.example.com/foo.crx",
+ "application/octet-stream", "application/x-chrome-extension" },
+
+ // success edge cases
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "http://www.example.com/foo.crx?query=string",
+ "", "application/x-chrome-extension" },
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "http://www.example.com/foo..crx",
+ "", "application/x-chrome-extension" },
+
+ // wrong file extension
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "http://www.example.com/foo.bin",
+ "", "application/octet-stream" },
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "http://www.example.com/foo.bin?monkey",
+ "", "application/octet-stream" },
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "invalid-url",
+ "", "application/octet-stream" },
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "http://www.example.com",
+ "", "application/octet-stream" },
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "http://www.example.com/",
+ "", "application/octet-stream" },
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "http://www.example.com/foo",
+ "", "application/octet-stream" },
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "http://www.example.com/foocrx",
+ "", "application/octet-stream" },
+ { "Cr24\x02\x00\x00\x00", sizeof("Cr24\x02\x00\x00\x00")-1,
+ "http://www.example.com/foo.crx.blech",
+ "", "application/octet-stream" },
+
+ // wrong magic
+ { "Cr24\x02\x00\x00\x01", sizeof("Cr24\x02\x00\x00\x01")-1,
+ "http://www.example.com/foo.crx?monkey",
+ "", "application/octet-stream" },
+ };
+
+ TestArray(tests, arraysize(tests));
+}
+
TEST(MimeSnifferTest, MozillaCompatibleTest) {
SnifferTest tests[] = {
{ " \n <hTmL>\n <hea", sizeof(" \n <hTmL>\n <hea")-1,