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