1// Copyright 2014 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
5#include "config.h"
6#include "core/frame/csp/MediaListDirective.h"
7
8#include "core/frame/csp/ContentSecurityPolicy.h"
9#include "platform/ParsingUtilities.h"
10#include "platform/network/ContentSecurityPolicyParsers.h"
11#include "wtf/HashSet.h"
12#include "wtf/text/WTFString.h"
13
14namespace blink {
15
16MediaListDirective::MediaListDirective(const String& name, const String& value, ContentSecurityPolicy* policy)
17    : CSPDirective(name, value, policy)
18{
19    Vector<UChar> characters;
20    value.appendTo(characters);
21    parse(characters.data(), characters.data() + characters.size());
22}
23
24bool MediaListDirective::allows(const String& type)
25{
26    return m_pluginTypes.contains(type);
27}
28
29void MediaListDirective::parse(const UChar* begin, const UChar* end)
30{
31    const UChar* position = begin;
32
33    // 'plugin-types ____;' OR 'plugin-types;'
34    if (position == end) {
35        policy()->reportInvalidPluginTypes(String());
36        return;
37    }
38
39    while (position < end) {
40        // _____ OR _____mime1/mime1
41        // ^        ^
42        skipWhile<UChar, isASCIISpace>(position, end);
43        if (position == end)
44            return;
45
46        // mime1/mime1 mime2/mime2
47        // ^
48        begin = position;
49        if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) {
50            skipWhile<UChar, isNotASCIISpace>(position, end);
51            policy()->reportInvalidPluginTypes(String(begin, position - begin));
52            continue;
53        }
54        skipWhile<UChar, isMediaTypeCharacter>(position, end);
55
56        // mime1/mime1 mime2/mime2
57        //      ^
58        if (!skipExactly<UChar>(position, end, '/')) {
59            skipWhile<UChar, isNotASCIISpace>(position, end);
60            policy()->reportInvalidPluginTypes(String(begin, position - begin));
61            continue;
62        }
63
64        // mime1/mime1 mime2/mime2
65        //       ^
66        if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) {
67            skipWhile<UChar, isNotASCIISpace>(position, end);
68            policy()->reportInvalidPluginTypes(String(begin, position - begin));
69            continue;
70        }
71        skipWhile<UChar, isMediaTypeCharacter>(position, end);
72
73        // mime1/mime1 mime2/mime2 OR mime1/mime1  OR mime1/mime1/error
74        //            ^                          ^               ^
75        if (position < end && isNotASCIISpace(*position)) {
76            skipWhile<UChar, isNotASCIISpace>(position, end);
77            policy()->reportInvalidPluginTypes(String(begin, position - begin));
78            continue;
79        }
80        m_pluginTypes.add(String(begin, position - begin));
81
82        ASSERT(position == end || isASCIISpace(*position));
83    }
84}
85
86} // namespace blink
87