f0d2c10b88f2087ebdabf157bc81b65c58081389
[WebKit-https.git] / Source / WebCore / platform / ContentType.cpp
1 /*
2  * Copyright (C) 2006, 2008, 2013 Apple Inc.  All rights reserved.
3  * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
4  * Copyright (C) 2009 Google Inc.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29 #include "ContentType.h"
30 #include "HTMLParserIdioms.h"
31 #include <wtf/JSONValues.h>
32 #include <wtf/NeverDestroyed.h>
33
34 namespace WebCore {
35
36 ContentType::ContentType(String&& contentType)
37     : m_type(WTFMove(contentType))
38 {
39 }
40
41 ContentType::ContentType(const String& contentType)
42     : m_type(contentType)
43 {
44 }
45
46 const String& ContentType::codecsParameter()
47 {
48     static NeverDestroyed<String> codecs { "codecs"_s };
49     return codecs;
50 }
51
52 const String& ContentType::profilesParameter()
53 {
54     static NeverDestroyed<String> profiles { "profiles"_s };
55     return profiles;
56 }
57
58 String ContentType::parameter(const String& parameterName) const
59 {
60     String parameterValue;
61     String strippedType = m_type.stripWhiteSpace();
62
63     // a MIME type can have one or more "param=value" after a semi-colon, and separated from each other by semi-colons
64     size_t semi = strippedType.find(';');
65     if (semi != notFound) {
66         size_t start = strippedType.findIgnoringASCIICase(parameterName, semi + 1);
67         if (start != notFound) {
68             start = strippedType.find('=', start + parameterName.length());
69             if (start != notFound) {
70                 size_t quote = strippedType.find('\"', start + 1);
71                 size_t end = strippedType.find('\"', start + 2);
72                 if (quote != notFound && end != notFound)
73                     start = quote;
74                 else {
75                     end = strippedType.find(';', start + 1);
76                     if (end == notFound)
77                         end = strippedType.length();
78                 }
79                 parameterValue = strippedType.substring(start + 1, end - (start + 1)).stripWhiteSpace();
80             }
81         }
82     }
83
84     return parameterValue;
85 }
86
87 String ContentType::containerType() const
88 {
89     String strippedType = m_type.stripWhiteSpace();
90
91     // "type" can have parameters after a semi-colon, strip them
92     size_t semi = strippedType.find(';');
93     if (semi != notFound)
94         strippedType = strippedType.left(semi).stripWhiteSpace();
95
96     return strippedType;
97 }
98
99 static inline Vector<String> splitParameters(StringView parametersView)
100 {
101     Vector<String> result;
102     for (auto view : parametersView.split(','))
103         result.append(view.stripLeadingAndTrailingMatchedCharacters(isHTMLSpace<UChar>).toString());
104     return result;
105 }
106
107 Vector<String> ContentType::codecs() const
108 {
109     return splitParameters(parameter(codecsParameter()));
110 }
111
112 Vector<String> ContentType::profiles() const
113 {
114     return splitParameters(parameter(profilesParameter()));
115 }
116
117 String ContentType::toJSONString() const
118 {
119     auto object = JSON::Object::create();
120
121     object->setString("containerType"_s, containerType());
122
123     auto codecs = codecsParameter();
124     if (!codecs.isEmpty())
125         object->setString("codecs"_s, codecs);
126
127     auto profiles = profilesParameter();
128     if (!profiles.isEmpty())
129         object->setString("profiles"_s, profiles);
130
131     return object->toJSONString();
132 }
133
134 } // namespace WebCore