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 "media/formats/webm/webm_content_encodings_client.h"
6
7 #include <stdint.h>
8
9 #include <string>
10
11 #include "base/bind.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "media/base/mock_media_log.h"
14 #include "media/formats/webm/webm_constants.h"
15 #include "media/formats/webm/webm_parser.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 using ::testing::StrictMock;
20
21 namespace media {
22
23 // Matchers for verifying common media log entry strings.
24 MATCHER(MissingContentEncoding, "") {
25 return CONTAINS_STRING(arg, "Missing ContentEncoding.");
26 }
27
28 MATCHER(UnexpectedContentEncodingOrder, "") {
29 return CONTAINS_STRING(arg, "Unexpected ContentEncodingOrder.");
30 }
31
32 MATCHER(UnexpectedContentEncodingScope, "") {
33 return CONTAINS_STRING(arg, "Unexpected ContentEncodingScope.");
34 }
35
36 MATCHER(ContentCompressionNotSupported, "") {
37 return CONTAINS_STRING(arg, "ContentCompression not supported.");
38 }
39
40 MATCHER(MissingContentEncryption, "") {
41 return CONTAINS_STRING(
42 arg,
43 "ContentEncodingType is encryption but ContentEncryption is missing.");
44 }
45
46 MATCHER_P(UnexpectedContentEncAlgo, algo, "") {
47 return CONTAINS_STRING(
48 arg, "Unexpected ContentEncAlgo " + base::NumberToString(algo) + ".");
49 }
50
51 class WebMContentEncodingsClientTest : public testing::Test {
52 public:
WebMContentEncodingsClientTest()53 WebMContentEncodingsClientTest()
54 : client_(&media_log_), parser_(kWebMIdContentEncodings, &client_) {}
55
ParseAndExpectToFail(const uint8_t * buf,int size)56 void ParseAndExpectToFail(const uint8_t* buf, int size) {
57 int result = parser_.Parse(buf, size);
58 EXPECT_EQ(-1, result);
59 }
60
61 protected:
62 StrictMock<MockMediaLog> media_log_;
63 WebMContentEncodingsClient client_;
64 WebMListParser parser_;
65 };
66
TEST_F(WebMContentEncodingsClientTest,EmptyContentEncodings)67 TEST_F(WebMContentEncodingsClientTest, EmptyContentEncodings) {
68 const uint8_t kContentEncodings[] = {
69 0x6D, 0x80, 0x80, // ContentEncodings (size = 0)
70 };
71 int size = sizeof(kContentEncodings);
72 EXPECT_MEDIA_LOG(MissingContentEncoding());
73 ParseAndExpectToFail(kContentEncodings, size);
74 }
75
TEST_F(WebMContentEncodingsClientTest,EmptyContentEncoding)76 TEST_F(WebMContentEncodingsClientTest, EmptyContentEncoding) {
77 const uint8_t kContentEncodings[] = {
78 0x6D, 0x80, 0x83, // ContentEncodings (size = 3)
79 0x63, 0x40, 0x80, // ContentEncoding (size = 0)
80 };
81 int size = sizeof(kContentEncodings);
82 ParseAndExpectToFail(kContentEncodings, size);
83 }
84
TEST_F(WebMContentEncodingsClientTest,SingleContentEncoding)85 TEST_F(WebMContentEncodingsClientTest, SingleContentEncoding) {
86 const uint8_t kContentEncodings[] = {
87 0x6D, 0x80, 0xA1, // ContentEncodings (size = 33)
88 0x62, 0x40, 0x9e, // ContentEncoding (size = 30)
89 0x50, 0x31, 0x81, 0x00, // ContentEncodingOrder (size = 1)
90 0x50, 0x32, 0x81, 0x01, // ContentEncodingScope (size = 1)
91 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
92 0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
93 0x47, 0xE1, 0x81, 0x05, // ContentEncAlgo (size = 1)
94 0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
95 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
96 };
97 int size = sizeof(kContentEncodings);
98
99 int result = parser_.Parse(kContentEncodings, size);
100 ASSERT_EQ(size, result);
101 const ContentEncodings& content_encodings = client_.content_encodings();
102
103 ASSERT_EQ(1u, content_encodings.size());
104 ASSERT_TRUE(content_encodings[0]);
105 EXPECT_EQ(0, content_encodings[0]->order());
106 EXPECT_EQ(ContentEncoding::kScopeAllFrameContents,
107 content_encodings[0]->scope());
108 EXPECT_EQ(ContentEncoding::kTypeEncryption, content_encodings[0]->type());
109 EXPECT_EQ(ContentEncoding::kEncAlgoAes,
110 content_encodings[0]->encryption_algo());
111 EXPECT_EQ(8u, content_encodings[0]->encryption_key_id().size());
112 }
113
TEST_F(WebMContentEncodingsClientTest,MultipleContentEncoding)114 TEST_F(WebMContentEncodingsClientTest, MultipleContentEncoding) {
115 const uint8_t kContentEncodings[] = {
116 0x6D, 0x80, 0xC2, // ContentEncodings (size = 66)
117 0x62, 0x40, 0x9e, // ContentEncoding (size = 30)
118 0x50, 0x31, 0x81, 0x00, // ContentEncodingOrder (size = 1)
119 0x50, 0x32, 0x81, 0x03, // ContentEncodingScope (size = 1)
120 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
121 0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
122 0x47, 0xE1, 0x81, 0x05, // ContentEncAlgo (size = 1)
123 0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
124 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
125 0x62, 0x40, 0x9e, // ContentEncoding (size = 30)
126 0x50, 0x31, 0x81, 0x01, // ContentEncodingOrder (size = 1)
127 0x50, 0x32, 0x81, 0x03, // ContentEncodingScope (size = 1)
128 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
129 0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
130 0x47, 0xE1, 0x81, 0x01, // ContentEncAlgo (size = 1)
131 0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
132 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
133 };
134 int size = sizeof(kContentEncodings);
135
136 int result = parser_.Parse(kContentEncodings, size);
137 ASSERT_EQ(size, result);
138 const ContentEncodings& content_encodings = client_.content_encodings();
139 ASSERT_EQ(2u, content_encodings.size());
140
141 for (int i = 0; i < 2; ++i) {
142 ASSERT_TRUE(content_encodings[i]);
143 EXPECT_EQ(i, content_encodings[i]->order());
144 EXPECT_EQ(ContentEncoding::kScopeAllFrameContents |
145 ContentEncoding::kScopeTrackPrivateData,
146 content_encodings[i]->scope());
147 EXPECT_EQ(ContentEncoding::kTypeEncryption, content_encodings[i]->type());
148 EXPECT_EQ(!i ? ContentEncoding::kEncAlgoAes : ContentEncoding::kEncAlgoDes,
149 content_encodings[i]->encryption_algo());
150 EXPECT_EQ(8u, content_encodings[i]->encryption_key_id().size());
151 }
152 }
153
TEST_F(WebMContentEncodingsClientTest,DefaultValues)154 TEST_F(WebMContentEncodingsClientTest, DefaultValues) {
155 const uint8_t kContentEncodings[] = {
156 0x6D, 0x80, 0x8A, // ContentEncodings (size = 10)
157 0x62, 0x40, 0x87, // ContentEncoding (size = 7)
158 // ContentEncodingOrder missing
159 // ContentEncodingScope missing
160 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
161 0x50, 0x35, 0x80, // ContentEncryption (size = 0)
162 // ContentEncAlgo missing
163 };
164 int size = sizeof(kContentEncodings);
165
166 int result = parser_.Parse(kContentEncodings, size);
167 ASSERT_EQ(size, result);
168 const ContentEncodings& content_encodings = client_.content_encodings();
169
170 ASSERT_EQ(1u, content_encodings.size());
171 ASSERT_TRUE(content_encodings[0]);
172 EXPECT_EQ(0, content_encodings[0]->order());
173 EXPECT_EQ(ContentEncoding::kScopeAllFrameContents,
174 content_encodings[0]->scope());
175 EXPECT_EQ(ContentEncoding::kTypeEncryption, content_encodings[0]->type());
176 EXPECT_EQ(ContentEncoding::kEncAlgoNotEncrypted,
177 content_encodings[0]->encryption_algo());
178 EXPECT_TRUE(content_encodings[0]->encryption_key_id().empty());
179 }
180
TEST_F(WebMContentEncodingsClientTest,ContentEncodingsClientReuse)181 TEST_F(WebMContentEncodingsClientTest, ContentEncodingsClientReuse) {
182 const uint8_t kContentEncodings[] = {
183 0x6D, 0x80, 0xA1, // ContentEncodings (size = 33)
184 0x62, 0x40, 0x9e, // ContentEncoding (size = 30)
185 0x50, 0x31, 0x81, 0x00, // ContentEncodingOrder (size = 1)
186 0x50, 0x32, 0x81, 0x01, // ContentEncodingScope (size = 1)
187 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
188 0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
189 0x47, 0xE1, 0x81, 0x05, // ContentEncAlgo (size = 1)
190 0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
191 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
192 };
193 int size = sizeof(kContentEncodings);
194
195 // Parse for the first time.
196 int result = parser_.Parse(kContentEncodings, size);
197 ASSERT_EQ(size, result);
198
199 // Parse again.
200 parser_.Reset();
201 result = parser_.Parse(kContentEncodings, size);
202 ASSERT_EQ(size, result);
203 const ContentEncodings& content_encodings = client_.content_encodings();
204
205 ASSERT_EQ(1u, content_encodings.size());
206 ASSERT_TRUE(content_encodings[0]);
207 EXPECT_EQ(0, content_encodings[0]->order());
208 EXPECT_EQ(ContentEncoding::kScopeAllFrameContents,
209 content_encodings[0]->scope());
210 EXPECT_EQ(ContentEncoding::kTypeEncryption, content_encodings[0]->type());
211 EXPECT_EQ(ContentEncoding::kEncAlgoAes,
212 content_encodings[0]->encryption_algo());
213 EXPECT_EQ(8u, content_encodings[0]->encryption_key_id().size());
214 }
215
TEST_F(WebMContentEncodingsClientTest,InvalidContentEncodingOrder)216 TEST_F(WebMContentEncodingsClientTest, InvalidContentEncodingOrder) {
217 const uint8_t kContentEncodings[] = {
218 0x6D, 0x80, 0x8E, // ContentEncodings (size = 14)
219 0x62, 0x40, 0x8B, // ContentEncoding (size = 11)
220 0x50, 0x31, 0x81, 0xEE, // ContentEncodingOrder (size = 1), invalid
221 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
222 0x50, 0x35, 0x80, // ContentEncryption (size = 0)
223 };
224 int size = sizeof(kContentEncodings);
225 EXPECT_MEDIA_LOG(UnexpectedContentEncodingOrder());
226 ParseAndExpectToFail(kContentEncodings, size);
227 }
228
TEST_F(WebMContentEncodingsClientTest,InvalidContentEncodingScope)229 TEST_F(WebMContentEncodingsClientTest, InvalidContentEncodingScope) {
230 const uint8_t kContentEncodings[] = {
231 0x6D, 0x80, 0x8E, // ContentEncodings (size = 14)
232 0x62, 0x40, 0x8B, // ContentEncoding (size = 11)
233 0x50, 0x32, 0x81, 0xEE, // ContentEncodingScope (size = 1), invalid
234 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
235 0x50, 0x35, 0x80, // ContentEncryption (size = 0)
236 };
237 int size = sizeof(kContentEncodings);
238 EXPECT_MEDIA_LOG(UnexpectedContentEncodingScope());
239 ParseAndExpectToFail(kContentEncodings, size);
240 }
241
TEST_F(WebMContentEncodingsClientTest,InvalidContentEncodingType)242 TEST_F(WebMContentEncodingsClientTest, InvalidContentEncodingType) {
243 const uint8_t kContentEncodings[] = {
244 0x6D, 0x80, 0x8E, // ContentEncodings (size = 14)
245 0x62, 0x40, 0x8B, // ContentEncoding (size = 11)
246 0x50, 0x33, 0x81, 0x00, // ContentEncodingType (size = 1), invalid
247 0x50, 0x35, 0x80, // ContentEncryption (size = 0)
248 };
249 int size = sizeof(kContentEncodings);
250 EXPECT_MEDIA_LOG(ContentCompressionNotSupported());
251 ParseAndExpectToFail(kContentEncodings, size);
252 }
253
254 // ContentEncodingType is encryption but no ContentEncryption present.
TEST_F(WebMContentEncodingsClientTest,MissingContentEncryption)255 TEST_F(WebMContentEncodingsClientTest, MissingContentEncryption) {
256 const uint8_t kContentEncodings[] = {
257 0x6D, 0x80, 0x87, // ContentEncodings (size = 7)
258 0x62, 0x40, 0x84, // ContentEncoding (size = 4)
259 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
260 // ContentEncryption missing
261 };
262 int size = sizeof(kContentEncodings);
263 EXPECT_MEDIA_LOG(MissingContentEncryption());
264 ParseAndExpectToFail(kContentEncodings, size);
265 }
266
TEST_F(WebMContentEncodingsClientTest,InvalidContentEncAlgo)267 TEST_F(WebMContentEncodingsClientTest, InvalidContentEncAlgo) {
268 const uint8_t kContentEncodings[] = {
269 0x6D, 0x80, 0x99, // ContentEncodings (size = 25)
270 0x62, 0x40, 0x96, // ContentEncoding (size = 22)
271 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
272 0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
273 0x47, 0xE1, 0x81, 0xEE, // ContentEncAlgo (size = 1), invalid
274 0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
275 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
276 };
277 int size = sizeof(kContentEncodings);
278 EXPECT_MEDIA_LOG(UnexpectedContentEncAlgo(0xEE));
279 ParseAndExpectToFail(kContentEncodings, size);
280 }
281
282 } // namespace media
283