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 @@
videoCapabilities: [{contentType: 'video/webm; foo="bar"; codecs="vp8"'}],
}], '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.
expect_error('org.w3.clearkey', [{
videoCapabilities: [{contentType: 'fake'}],
......
......@@ -51,7 +51,7 @@ static WebVector<WebMediaKeySystemMediaCapability> convertCapabilities(
for (size_t i = 0; i < capabilities.size(); ++i) {
const WebString& contentType = capabilities[i].contentType();
result[i].contentType = contentType;
ParsedContentType type(contentType);
ParsedContentType type(contentType, ParsedContentType::Mode::Strict);
if (type.isValid()) {
// From
// http://w3c.github.io/encrypted-media/#get-supported-capabilities-for-audio-video-type
......
......@@ -264,11 +264,15 @@ bool ParsedContentType::parse(const String& contentType) {
<< ", for '" << key.toString() << "').";
return false;
}
String keyString = key.toString();
// As |key| is parsed as a token, it consists of ascii characters
// and hence we don't need to care about non-ascii lowercasing.
DCHECK(keyString.containsOnlyASCII());
map.set(keyString.lower(), value);
DCHECK(key.toString().containsOnlyASCII());
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);
return true;
......
......@@ -49,9 +49,13 @@ class PLATFORM_EXPORT ParsedContentType final {
// When |Relaxed| is specified, the parser parses parameter values in a sloppy
// manner, i.e., only ';' and '"' are treated as special characters.
// 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 {
Normal,
Relaxed,
Strict,
};
explicit ParsedContentType(const String&, Mode = Mode::Normal);
......
......@@ -133,6 +133,13 @@ TEST(ParsedContentTypeTest, RelaxedParameterName) {
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 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