Commit 5f918117 authored by jrummell's avatar jrummell Committed by Commit bot

Allow ParsedContentType to reject multiple definitions of the same parameter

The code in ParsedContentType is based on RFC2045, which does not mention what
should happen if the same parameter name is mentioned multiple times. However,
RFC6838 (Media Type Specifications and Registration Procedures), which defines
the MIME types for media and is based on RFC2045/2046, has the following
statement:
  It is an error for a specific parameter to be specified more than once.

Add an option to have ParsedContentType fail if the same parameter is
specified multiple times. navigator.requestMediaKeySystemAccess() is updated
to reject MIME types that mention the same parameter name more than once.

BUG=698436
TEST=new tests pass

Review-Url: https://codereview.chromium.org/2736283002
Cr-Commit-Position: refs/heads/master@{#456167}
parent 2a2a964c
...@@ -314,6 +314,11 @@ ...@@ -314,6 +314,11 @@
videoCapabilities: [{contentType: 'video/webm; foo="bar"; codecs="vp8"'}], videoCapabilities: [{contentType: 'video/webm; foo="bar"; codecs="vp8"'}],
}], 'NotSupportedError', 'Unrecognized foo with codecs'); }], 'NotSupportedError', 'Unrecognized foo with codecs');
// Multiple parameters with the same name are not allowed (RFC6838).
expect_error('org.w3.clearkey', [{
videoCapabilities: [{contentType: 'video/webm; codecs=vp8; codecs=vp9'}],
}], 'NotSupportedError', 'Multiple codecs');
// Invalid contentTypes. // Invalid contentTypes.
expect_error('org.w3.clearkey', [{ expect_error('org.w3.clearkey', [{
videoCapabilities: [{contentType: 'fake'}], videoCapabilities: [{contentType: 'fake'}],
......
...@@ -51,7 +51,7 @@ static WebVector<WebMediaKeySystemMediaCapability> convertCapabilities( ...@@ -51,7 +51,7 @@ static WebVector<WebMediaKeySystemMediaCapability> convertCapabilities(
for (size_t i = 0; i < capabilities.size(); ++i) { for (size_t i = 0; i < capabilities.size(); ++i) {
const WebString& contentType = capabilities[i].contentType(); const WebString& contentType = capabilities[i].contentType();
result[i].contentType = contentType; result[i].contentType = contentType;
ParsedContentType type(contentType); ParsedContentType type(contentType, ParsedContentType::Mode::Strict);
if (type.isValid()) { if (type.isValid()) {
// From // From
// http://w3c.github.io/encrypted-media/#get-supported-capabilities-for-audio-video-type // http://w3c.github.io/encrypted-media/#get-supported-capabilities-for-audio-video-type
......
...@@ -264,11 +264,15 @@ bool ParsedContentType::parse(const String& contentType) { ...@@ -264,11 +264,15 @@ bool ParsedContentType::parse(const String& contentType) {
<< ", for '" << key.toString() << "')."; << ", for '" << key.toString() << "').";
return false; return false;
} }
String keyString = key.toString();
// As |key| is parsed as a token, it consists of ascii characters // As |key| is parsed as a token, it consists of ascii characters
// and hence we don't need to care about non-ascii lowercasing. // and hence we don't need to care about non-ascii lowercasing.
DCHECK(keyString.containsOnlyASCII()); DCHECK(key.toString().containsOnlyASCII());
map.set(keyString.lower(), value); String keyString = key.toString().lower();
if (m_mode == Mode::Strict && map.find(keyString) != map.end()) {
DVLOG(1) << "Parameter " << keyString << " is defined multiple times.";
return false;
}
map.set(keyString, value);
} }
m_parameters = std::move(map); m_parameters = std::move(map);
return true; return true;
......
...@@ -49,9 +49,13 @@ class PLATFORM_EXPORT ParsedContentType final { ...@@ -49,9 +49,13 @@ class PLATFORM_EXPORT ParsedContentType final {
// When |Relaxed| is specified, the parser parses parameter values in a sloppy // When |Relaxed| is specified, the parser parses parameter values in a sloppy
// manner, i.e., only ';' and '"' are treated as special characters. // manner, i.e., only ';' and '"' are treated as special characters.
// See https://chromiumcodereview.appspot.com/23043002. // See https://chromiumcodereview.appspot.com/23043002.
// When |Strict| is specified, the parser does not allow multiple values
// for the same parameter. Some RFCs based on RFC2045 (e.g. RFC6838) note that
// "It is an error for a specific parameter to be specified more than once."
enum class Mode { enum class Mode {
Normal, Normal,
Relaxed, Relaxed,
Strict,
}; };
explicit ParsedContentType(const String&, Mode = Mode::Normal); explicit ParsedContentType(const String&, Mode = Mode::Normal);
......
...@@ -133,6 +133,13 @@ TEST(ParsedContentTypeTest, RelaxedParameterName) { ...@@ -133,6 +133,13 @@ TEST(ParsedContentTypeTest, RelaxedParameterName) {
EXPECT_EQ("u", t.parameterValueForName("y")); EXPECT_EQ("u", t.parameterValueForName("y"));
} }
TEST(ParsedContentTypeTest, StrictParameterName) {
EXPECT_TRUE(isValid("text/plain", Mode::Strict));
EXPECT_TRUE(isValid("text/plain; p1=a", Mode::Strict));
EXPECT_FALSE(isValid("text/plain; p1=a; p1=b", Mode::Strict));
EXPECT_TRUE(isValid("text/plain; p1=a; p2=b", Mode::Strict));
}
} // namespace } // namespace
} // namespace blink } // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment