OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/fetch/MultipartImageResourceParser.h" | 5 #include "core/fetch/MultipartImageResourceParser.h" |
6 | 6 |
7 #include "platform/network/ResourceResponse.h" | 7 #include "platform/network/ResourceResponse.h" |
8 #include "public/platform/Platform.h" | 8 #include "public/platform/Platform.h" |
9 #include "public/platform/WebURL.h" | 9 #include "public/platform/WebURL.h" |
10 #include "public/platform/WebURLResponse.h" | 10 #include "public/platform/WebURLResponse.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 } | 36 } |
37 void multipartDataReceived(const char* bytes, size_t size) override | 37 void multipartDataReceived(const char* bytes, size_t size) override |
38 { | 38 { |
39 m_data.last().append(bytes, size); | 39 m_data.last().append(bytes, size); |
40 } | 40 } |
41 | 41 |
42 Vector<ResourceResponse> m_responses; | 42 Vector<ResourceResponse> m_responses; |
43 Vector<Vector<char>> m_data; | 43 Vector<Vector<char>> m_data; |
44 }; | 44 }; |
45 | 45 |
46 TEST(MultipartResponseTest, PushOverLine) | 46 TEST(MultipartResponseTest, SkippableLength) |
47 { | 47 { |
48 struct { | 48 struct { |
49 const char* input; | 49 const char* input; |
50 const size_t position; | 50 const size_t position; |
51 const size_t expected; | 51 const size_t expected; |
52 } lineTests[] = { | 52 } lineTests[] = { |
53 { "Line", 0, 0 }, | 53 { "Line", 0, 0 }, |
54 { "Line", 2, 0 }, | 54 { "Line", 2, 0 }, |
55 { "Line", 10, 0 }, | 55 { "Line", 10, 0 }, |
56 { "\r\nLine", 0, 2 }, | 56 { "\r\nLine", 0, 2 }, |
57 { "\nLine", 0, 1 }, | 57 { "\nLine", 0, 1 }, |
58 { "\n\nLine", 0, 2 }, | 58 { "\n\nLine", 0, 1 }, |
59 { "\rLine", 0, 1 }, | 59 { "\rLine", 0, 0 }, |
60 { "Line\r\nLine", 4, 2 }, | 60 { "Line\r\nLine", 4, 2 }, |
61 { "Line\nLine", 4, 1 }, | 61 { "Line\nLine", 4, 1 }, |
62 { "Line\n\nLine", 4, 2 }, | 62 { "Line\n\nLine", 4, 1 }, |
63 { "Line\rLine", 4, 1 }, | 63 { "Line\rLine", 4, 0 }, |
64 { "Line\r\rLine", 4, 1 }, | 64 { "Line\r\rLine", 4, 0 }, |
65 }; | 65 }; |
66 for (size_t i = 0; i < WTF_ARRAY_LENGTH(lineTests); ++i) { | 66 for (size_t i = 0; i < WTF_ARRAY_LENGTH(lineTests); ++i) { |
67 Vector<char> input; | 67 Vector<char> input; |
68 input.append(lineTests[i].input, strlen(lineTests[i].input)); | 68 input.append(lineTests[i].input, strlen(lineTests[i].input)); |
69 EXPECT_EQ(lineTests[i].expected, | 69 EXPECT_EQ(lineTests[i].expected, |
70 MultipartImageResourceParser::pushOverLineForTest(input, lineTests[i
].position)); | 70 MultipartImageResourceParser::skippableLengthForTest(input, lineTest
s[i].position)); |
71 } | 71 } |
72 } | 72 } |
73 | 73 |
74 TEST(MultipartResponseTest, ParseMultipartHeadersResult) | 74 TEST(MultipartResponseTest, ParseMultipartHeadersResult) |
75 { | 75 { |
76 struct { | 76 struct { |
77 const char* data; | 77 const char* data; |
78 const bool result; | 78 const bool result; |
79 const size_t end; | 79 const size_t end; |
80 } tests[] = { | 80 } tests[] = { |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 Vector<char> boundary; | 194 Vector<char> boundary; |
195 boundary.append("bound", 5); | 195 boundary.append("bound", 5); |
196 | 196 |
197 MultipartImageResourceParser* parser = new MultipartImageResourceParser(resp
onse, boundary, client); | 197 MultipartImageResourceParser* parser = new MultipartImageResourceParser(resp
onse, boundary, client); |
198 const char data[] = | 198 const char data[] = |
199 "bound\nContent-type: text/plain\n\n" | 199 "bound\nContent-type: text/plain\n\n" |
200 "This is a sample response\n"; | 200 "This is a sample response\n"; |
201 parser->appendData(data, strlen(data)); | 201 parser->appendData(data, strlen(data)); |
202 ASSERT_EQ(1u, client->m_responses.size()); | 202 ASSERT_EQ(1u, client->m_responses.size()); |
203 ASSERT_EQ(1u, client->m_data.size()); | 203 ASSERT_EQ(1u, client->m_data.size()); |
204 EXPECT_EQ("This is a sample response\n", toString(client->m_data[0])); | 204 EXPECT_EQ("This is a sample ", toString(client->m_data[0])); |
205 | 205 |
206 parser->finish(); | 206 parser->finish(); |
207 ASSERT_EQ(1u, client->m_responses.size()); | 207 ASSERT_EQ(1u, client->m_responses.size()); |
208 ASSERT_EQ(1u, client->m_data.size()); | 208 ASSERT_EQ(1u, client->m_data.size()); |
209 EXPECT_EQ("This is a sample response\n", toString(client->m_data[0])); | 209 EXPECT_EQ("This is a sample response\n", toString(client->m_data[0])); |
210 } | 210 } |
211 | 211 |
212 TEST(MultipartResponseTest, NoStartAndEndBoundary) | 212 TEST(MultipartResponseTest, NoStartAndEndBoundary) |
213 { | 213 { |
214 ResourceResponse response; | 214 ResourceResponse response; |
215 response.setMimeType("multipart/x-mixed-replace"); | 215 response.setMimeType("multipart/x-mixed-replace"); |
216 response.setHTTPHeaderField("Foo", "Bar"); | 216 response.setHTTPHeaderField("Foo", "Bar"); |
217 response.setHTTPHeaderField("Content-type", "text/plain"); | 217 response.setHTTPHeaderField("Content-type", "text/plain"); |
218 MockClient* client = new MockClient; | 218 MockClient* client = new MockClient; |
219 Vector<char> boundary; | 219 Vector<char> boundary; |
220 boundary.append("bound", 5); | 220 boundary.append("bound", 5); |
221 | 221 |
222 MultipartImageResourceParser* parser = new MultipartImageResourceParser(resp
onse, boundary, client); | 222 MultipartImageResourceParser* parser = new MultipartImageResourceParser(resp
onse, boundary, client); |
223 const char data[] = | 223 const char data[] = |
224 "Content-type: text/plain\n\n" | 224 "Content-type: text/plain\n\n" |
225 "This is a sample response\n"; | 225 "This is a sample response\n"; |
226 parser->appendData(data, strlen(data)); | 226 parser->appendData(data, strlen(data)); |
227 ASSERT_EQ(1u, client->m_responses.size()); | 227 ASSERT_EQ(1u, client->m_responses.size()); |
228 ASSERT_EQ(1u, client->m_data.size()); | 228 ASSERT_EQ(1u, client->m_data.size()); |
229 EXPECT_EQ("This is a sample response\n", toString(client->m_data[0])); | 229 EXPECT_EQ("This is a sample ", toString(client->m_data[0])); |
230 | 230 |
231 parser->finish(); | 231 parser->finish(); |
232 ASSERT_EQ(1u, client->m_responses.size()); | 232 ASSERT_EQ(1u, client->m_responses.size()); |
233 ASSERT_EQ(1u, client->m_data.size()); | 233 ASSERT_EQ(1u, client->m_data.size()); |
234 EXPECT_EQ("This is a sample response\n", toString(client->m_data[0])); | 234 EXPECT_EQ("This is a sample response\n", toString(client->m_data[0])); |
235 } | 235 } |
236 | 236 |
237 TEST(MultipartResponseTest, MalformedBoundary) | 237 TEST(MultipartResponseTest, MalformedBoundary) |
238 { | 238 { |
239 // Some servers send a boundary that is prefixed by "--". See bug 5786. | 239 // Some servers send a boundary that is prefixed by "--". See bug 5786. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 // Break in the first boundary | 315 // Break in the first boundary |
316 const TestChunk bound1[] = { | 316 const TestChunk bound1[] = { |
317 { 0, 4, 0, "" }, | 317 { 0, 4, 0, "" }, |
318 { 4, 110, 2, "foofoofoofoofoo" }, | 318 { 4, 110, 2, "foofoofoofoofoo" }, |
319 }; | 319 }; |
320 variousChunkSizesTest(bound1, 2, 2, "foofoofoofoofoo"); | 320 variousChunkSizesTest(bound1, 2, 2, "foofoofoofoofoo"); |
321 | 321 |
322 // Break in first and second | 322 // Break in first and second |
323 const TestChunk bound2[] = { | 323 const TestChunk bound2[] = { |
324 { 0, 4, 0, "" }, | 324 { 0, 4, 0, "" }, |
325 { 4, 55, 1, "datadatadatadat" }, | 325 { 4, 55, 1, "datadatadatad" }, |
326 { 55, 65, 1, "datadatadatadatadata" }, | 326 { 55, 65, 1, "datadatadatadatadata" }, |
327 { 65, 110, 2, "foofoofoofoofoo" }, | 327 { 65, 110, 2, "foofoofoofoofoo" }, |
328 }; | 328 }; |
329 variousChunkSizesTest(bound2, 2, 3, "foofoofoofoofoo"); | 329 variousChunkSizesTest(bound2, 2, 3, "foofoofoofoofoo"); |
330 | 330 |
331 // Break in second only | 331 // Break in second only |
332 const TestChunk bound3[] = { | 332 const TestChunk bound3[] = { |
333 { 0, 55, 1, "datadatadatadat" }, | 333 { 0, 55, 1, "datadatadatad" }, |
334 { 55, 110, 2, "foofoofoofoofoo" }, | 334 { 55, 110, 2, "foofoofoofoofoo" }, |
335 }; | 335 }; |
336 variousChunkSizesTest(bound3, 2, 3, "foofoofoofoofoo"); | 336 variousChunkSizesTest(bound3, 2, 3, "foofoofoofoofoo"); |
337 } | 337 } |
338 | 338 |
339 TEST(MultipartResponseTest, BreakInHeaders) | 339 TEST(MultipartResponseTest, BreakInHeaders) |
340 { | 340 { |
341 // Break in first header | 341 // Break in first header |
342 const TestChunk header1[] = { | 342 const TestChunk header1[] = { |
343 { 0, 10, 0, "" }, | 343 { 0, 10, 0, "" }, |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 MultipartImageResourceParser* parser = new MultipartImageResourceParser(resp
onse, boundary, client); | 435 MultipartImageResourceParser* parser = new MultipartImageResourceParser(resp
onse, boundary, client); |
436 | 436 |
437 const char data[] = "--bound\r\n\r\n--bound\r\n\r\nfoofoo--bound--"; | 437 const char data[] = "--bound\r\n\r\n--bound\r\n\r\nfoofoo--bound--"; |
438 parser->appendData(data, strlen(data)); | 438 parser->appendData(data, strlen(data)); |
439 ASSERT_EQ(2u, client->m_responses.size()); | 439 ASSERT_EQ(2u, client->m_responses.size()); |
440 ASSERT_EQ(2u, client->m_data.size()); | 440 ASSERT_EQ(2u, client->m_data.size()); |
441 EXPECT_EQ("", toString(client->m_data[0])); | 441 EXPECT_EQ("", toString(client->m_data[0])); |
442 EXPECT_EQ("foofoo", toString(client->m_data[1])); | 442 EXPECT_EQ("foofoo", toString(client->m_data[1])); |
443 } | 443 } |
444 | 444 |
| 445 TEST(MultipartResponseTest, EatLeadingLF) |
| 446 { |
| 447 ResourceResponse response; |
| 448 response.setMimeType("multipart/x-mixed-replace"); |
| 449 MockClient* client = new MockClient; |
| 450 Vector<char> boundary; |
| 451 boundary.append("bound", 5); |
| 452 |
| 453 const char data[] = |
| 454 "\n\n\n--bound\n\n\ncontent-type: 1\n\n" |
| 455 "\n\n\n--bound\n\ncontent-type: 2\n\n" |
| 456 "\n\n\n--bound\ncontent-type: 3\n\n"; |
| 457 MultipartImageResourceParser* parser = new MultipartImageResourceParser(resp
onse, boundary, client); |
| 458 |
| 459 for (size_t i = 0; i < strlen(data); ++i) |
| 460 parser->appendData(&data[i], 1); |
| 461 parser->finish(); |
| 462 |
| 463 ASSERT_EQ(4u, client->m_responses.size()); |
| 464 ASSERT_EQ(4u, client->m_data.size()); |
| 465 EXPECT_EQ(String(), client->m_responses[0].httpHeaderField("content-type")); |
| 466 EXPECT_EQ("", toString(client->m_data[0])); |
| 467 EXPECT_EQ(String(), client->m_responses[1].httpHeaderField("content-type")); |
| 468 EXPECT_EQ("\ncontent-type: 1\n\n\n\n", toString(client->m_data[1])); |
| 469 EXPECT_EQ(String(), client->m_responses[2].httpHeaderField("content-type")); |
| 470 EXPECT_EQ("content-type: 2\n\n\n\n", toString(client->m_data[2])); |
| 471 EXPECT_EQ("3", client->m_responses[3].httpHeaderField("content-type")); |
| 472 EXPECT_EQ("", toString(client->m_data[3])); |
| 473 } |
| 474 |
| 475 TEST(MultipartResponseTest, EatLeadingCRLF) |
| 476 { |
| 477 ResourceResponse response; |
| 478 response.setMimeType("multipart/x-mixed-replace"); |
| 479 MockClient* client = new MockClient; |
| 480 Vector<char> boundary; |
| 481 boundary.append("bound", 5); |
| 482 |
| 483 const char data[] = |
| 484 "\r\n\r\n\r\n--bound\r\n\r\n\r\ncontent-type: 1\r\n\r\n" |
| 485 "\r\n\r\n\r\n--bound\r\n\r\ncontent-type: 2\r\n\r\n" |
| 486 "\r\n\r\n\r\n--bound\r\ncontent-type: 3\r\n\r\n"; |
| 487 MultipartImageResourceParser* parser = new MultipartImageResourceParser(resp
onse, boundary, client); |
| 488 |
| 489 for (size_t i = 0; i < strlen(data); ++i) |
| 490 parser->appendData(&data[i], 1); |
| 491 parser->finish(); |
| 492 |
| 493 ASSERT_EQ(4u, client->m_responses.size()); |
| 494 ASSERT_EQ(4u, client->m_data.size()); |
| 495 EXPECT_EQ(String(), client->m_responses[0].httpHeaderField("content-type")); |
| 496 EXPECT_EQ("", toString(client->m_data[0])); |
| 497 EXPECT_EQ(String(), client->m_responses[1].httpHeaderField("content-type")); |
| 498 EXPECT_EQ("\r\ncontent-type: 1\r\n\r\n\r\n\r\n", toString(client->m_data[1])
); |
| 499 EXPECT_EQ(String(), client->m_responses[2].httpHeaderField("content-type")); |
| 500 EXPECT_EQ("content-type: 2\r\n\r\n\r\n\r\n", toString(client->m_data[2])); |
| 501 EXPECT_EQ("3", client->m_responses[3].httpHeaderField("content-type")); |
| 502 EXPECT_EQ("", toString(client->m_data[3])); |
| 503 } |
| 504 |
445 } // namespace | 505 } // namespace |
446 | 506 |
447 } // namespace blink | 507 } // namespace blink |
OLD | NEW |