diff options
author | gbillock@chromium.org <gbillock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-26 03:50:56 +0000 |
---|---|---|
committer | gbillock@chromium.org <gbillock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-26 03:50:56 +0000 |
commit | ad50e8b3bba31d489c91202f6709f80510108b6e (patch) | |
tree | d2ff26dd47808b8d3903d25396ccef6731081614 | |
parent | d3add5cf33fe302d5fb15f34712dc380e787c5ae (diff) | |
download | chromium_src-ad50e8b3bba31d489c91202f6709f80510108b6e.zip chromium_src-ad50e8b3bba31d489c91202f6709f80510108b6e.tar.gz chromium_src-ad50e8b3bba31d489c91202f6709f80510108b6e.tar.bz2 |
Update mime type matching to handle parameters.
R=rvargas@chromium.org
BUG=None
Review URL: https://chromiumcodereview.appspot.com/11193023
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@164256 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/intents/web_intents_util_unittest.cc | 13 | ||||
-rw-r--r-- | net/base/mime_util.cc | 78 | ||||
-rw-r--r-- | net/base/mime_util_unittest.cc | 41 |
3 files changed, 116 insertions, 16 deletions
diff --git a/chrome/browser/intents/web_intents_util_unittest.cc b/chrome/browser/intents/web_intents_util_unittest.cc index 910b809..931204b 100644 --- a/chrome/browser/intents/web_intents_util_unittest.cc +++ b/chrome/browser/intents/web_intents_util_unittest.cc @@ -79,4 +79,17 @@ TEST(WebIntentsUtilTest, MimeTypesMatchWildCards) { EXPECT_FALSE(TypesMatch("**", "image/png")); } +TEST(WebIntentsUtilTest, MimeTypesMatchParameters) { + EXPECT_TRUE(TypesMatch("*", "video/*;single=true")); + EXPECT_TRUE(TypesMatch("*/*", "video/mpg;single=true")); + EXPECT_TRUE(TypesMatch("video/*", "video/mpg;single=true")); + EXPECT_TRUE(TypesMatch("video/mpg", "video/mpg;single=true")); + EXPECT_TRUE(TypesMatch("video/mpg;single=true", "video/mpg;single=true")); + EXPECT_TRUE(TypesMatch("video/mpg;a=b;single=true", + "video/mpg;single=true;a=b")); + EXPECT_FALSE(TypesMatch("video/mpg;a=b;single=true", + "video/mpg;single=false;a=b")); + EXPECT_FALSE(TypesMatch("video/mpg;single=true", "video/mpg;single=false")); +} + } // namepsace web_intents diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc index f851ecd..e8d1813 100644 --- a/net/base/mime_util.cc +++ b/net/base/mime_util.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <algorithm> +#include <iterator> #include <map> #include <string> @@ -511,41 +513,85 @@ bool MimeUtil::IsSupportedMimeType(const std::string& mime_type) const { IsSupportedNonImageMimeType(mime_type); } +// Tests for MIME parameter equality. Each parameter in the |mime_type_pattern| +// must be matched by a parameter in the |mime_type|. If there are no +// parameters in the pattern, the match is a success. +bool MatchesMimeTypeParameters(const std::string& mime_type_pattern, + const std::string& mime_type) { + const std::string::size_type semicolon = mime_type_pattern.find(';'); + const std::string::size_type test_semicolon = mime_type.find(';'); + if (semicolon != std::string::npos) { + if (test_semicolon == std::string::npos) + return false; + + std::vector<std::string> pattern_parameters; + base::SplitString(mime_type_pattern.substr(semicolon + 1), + ';', &pattern_parameters); + + std::vector<std::string> test_parameters; + base::SplitString(mime_type.substr(test_semicolon + 1), + ';', &test_parameters); + + sort(pattern_parameters.begin(), pattern_parameters.end()); + sort(test_parameters.begin(), test_parameters.end()); + std::vector<std::string> difference; + std::set_difference(pattern_parameters.begin(), pattern_parameters.end(), + test_parameters.begin(), test_parameters.end(), + std::inserter(difference, difference.begin())); + + return difference.size() == 0; + } + return true; +} + +// This comparison handles absolute maching and also basic +// wildcards. The plugin mime types could be: +// application/x-foo +// application/* +// application/*+xml +// * +// Also tests mime parameters -- all parameters in the pattern must be present +// in the tested type for a match to succeed. bool MimeUtil::MatchesMimeType(const std::string& mime_type_pattern, const std::string& mime_type) const { - // verify caller is passing lowercase + // Verify caller is passing lowercase strings. DCHECK_EQ(StringToLowerASCII(mime_type_pattern), mime_type_pattern); DCHECK_EQ(StringToLowerASCII(mime_type), mime_type); - // This comparison handles absolute maching and also basic - // wildcards. The plugin mime types could be: - // application/x-foo - // application/* - // application/*+xml - // * if (mime_type_pattern.empty()) return false; - const std::string::size_type star = mime_type_pattern.find('*'); + std::string::size_type semicolon = mime_type_pattern.find(';'); + const std::string base_pattern(mime_type_pattern.substr(0, semicolon)); + semicolon = mime_type.find(';'); + const std::string base_type(mime_type.substr(0, semicolon)); + + if (base_pattern == "*" || base_pattern == "*/*") + return MatchesMimeTypeParameters(mime_type_pattern, mime_type); - if (star == std::string::npos) - return mime_type_pattern == mime_type; + const std::string::size_type star = base_pattern.find('*'); + if (star == std::string::npos) { + if (base_pattern == base_type) + return MatchesMimeTypeParameters(mime_type_pattern, mime_type); + else + return false; + } // Test length to prevent overlap between |left| and |right|. - if (mime_type.length() < mime_type_pattern.length() - 1) + if (base_type.length() < base_pattern.length() - 1) return false; - const std::string left(mime_type_pattern.substr(0, star)); - const std::string right(mime_type_pattern.substr(star + 1)); + const std::string left(base_pattern.substr(0, star)); + const std::string right(base_pattern.substr(star + 1)); - if (mime_type.find(left) != 0) + if (base_type.find(left) != 0) return false; if (!right.empty() && - mime_type.rfind(right) != mime_type.length() - right.length()) + base_type.rfind(right) != base_type.length() - right.length()) return false; - return true; + return MatchesMimeTypeParameters(mime_type_pattern, mime_type); } // See http://www.iana.org/assignments/media-types/index.html diff --git a/net/base/mime_util_unittest.cc b/net/base/mime_util_unittest.cc index 635b517..225b668 100644 --- a/net/base/mime_util_unittest.cc +++ b/net/base/mime_util_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/basictypes.h" +#include "base/string_split.h" #include "base/utf_string_conversions.h" #include "net/base/mime_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -98,6 +99,46 @@ TEST(MimeUtilTest, MatchesMimeType) { EXPECT_FALSE(MatchesMimeType("application/*+xml", "applcation/html+xml")); EXPECT_FALSE(MatchesMimeType("aaa*aaa", "aaaaa")); + + EXPECT_TRUE(MatchesMimeType("*", "video/x-mpeg;param=val")); + EXPECT_TRUE(MatchesMimeType("video/*", "video/x-mpeg;param=val")); + EXPECT_FALSE(MatchesMimeType("video/*;param=val", "video/mpeg")); + EXPECT_FALSE(MatchesMimeType("video/*;param=val", "video/mpeg;param=other")); + EXPECT_TRUE(MatchesMimeType("video/*;param=val", "video/mpeg;param=val")); + EXPECT_TRUE(MatchesMimeType("video/x-mpeg", "video/x-mpeg;param=val")); + EXPECT_TRUE(MatchesMimeType("video/x-mpeg;param=val", + "video/x-mpeg;param=val")); + EXPECT_FALSE(MatchesMimeType("video/x-mpeg;param2=val2", + "video/x-mpeg;param=val")); + EXPECT_FALSE(MatchesMimeType("video/x-mpeg;param2=val2", + "video/x-mpeg;param2=val")); + EXPECT_TRUE(MatchesMimeType("video/x-mpeg;param=val", + "video/x-mpeg;param=val;param2=val2")); + EXPECT_TRUE(MatchesMimeType("video/x-mpeg;param=val;param2=val2", + "video/x-mpeg;param=val;param2=val2")); + EXPECT_TRUE(MatchesMimeType("video/x-mpeg;param2=val2;param=val", + "video/x-mpeg;param=val;param2=val2")); + EXPECT_FALSE(MatchesMimeType("video/x-mpeg;param3=val3;param=val", + "video/x-mpeg;param=val;param2=val2")); + EXPECT_TRUE(MatchesMimeType("video/x-mpeg;param=val ;param2=val2 ", + "video/x-mpeg;param=val;param2=val2")); + + EXPECT_TRUE(MatchesMimeType("*/*;param=val", "video/x-mpeg;param=val")); + EXPECT_FALSE(MatchesMimeType("*/*;param=val", "video/x-mpeg;param=val2")); + + EXPECT_TRUE(MatchesMimeType("*", "*")); + EXPECT_TRUE(MatchesMimeType("*", "*/*")); + EXPECT_TRUE(MatchesMimeType("*/*", "*/*")); + EXPECT_TRUE(MatchesMimeType("*/*", "*")); + EXPECT_TRUE(MatchesMimeType("video/*", "video/*")); + EXPECT_FALSE(MatchesMimeType("video/*", "*/*")); + EXPECT_FALSE(MatchesMimeType("video/*;param=val", "video/*")); + EXPECT_TRUE(MatchesMimeType("video/*;param=val", "video/*;param=val")); + EXPECT_FALSE(MatchesMimeType("video/*;param=val", "video/*;param=val2")); + + EXPECT_TRUE(MatchesMimeType("ab*cd", "abxxxcd")); + EXPECT_TRUE(MatchesMimeType("ab*cd", "abx/xcd")); + EXPECT_TRUE(MatchesMimeType("ab/*cd", "ab/xxxcd")); } // Note: codecs should only be a list of 2 or fewer; hence the restriction of |