OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <queue> | 5 #include <queue> |
6 #include <map> | 6 #include <map> |
7 | 7 |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 13 matching lines...) Expand all Loading... | |
24 #include "chrome/common/extensions/extension_messages.h" | 24 #include "chrome/common/extensions/extension_messages.h" |
25 #include "chrome/common/pref_names.h" | 25 #include "chrome/common/pref_names.h" |
26 #include "chrome/test/base/testing_browser_process.h" | 26 #include "chrome/test/base/testing_browser_process.h" |
27 #include "chrome/test/base/testing_pref_service.h" | 27 #include "chrome/test/base/testing_pref_service.h" |
28 #include "chrome/test/base/testing_profile.h" | 28 #include "chrome/test/base/testing_profile.h" |
29 #include "content/public/test/test_browser_thread.h" | 29 #include "content/public/test/test_browser_thread.h" |
30 #include "net/base/auth.h" | 30 #include "net/base/auth.h" |
31 #include "net/base/capturing_net_log.h" | 31 #include "net/base/capturing_net_log.h" |
32 #include "net/base/mock_host_resolver.h" | 32 #include "net/base/mock_host_resolver.h" |
33 #include "net/base/net_util.h" | 33 #include "net/base/net_util.h" |
34 #include "net/base/upload_data.h" | |
34 #include "net/url_request/url_request_test_util.h" | 35 #include "net/url_request/url_request_test_util.h" |
35 #include "testing/gtest/include/gtest/gtest.h" | 36 #include "testing/gtest/include/gtest/gtest.h" |
36 | 37 |
37 namespace helpers = extension_web_request_api_helpers; | 38 namespace helpers = extension_web_request_api_helpers; |
38 namespace keys = extension_web_request_api_constants; | 39 namespace keys = extension_web_request_api_constants; |
39 | 40 |
40 using helpers::CalculateOnAuthRequiredDelta; | 41 using helpers::CalculateOnAuthRequiredDelta; |
41 using helpers::CalculateOnBeforeRequestDelta; | 42 using helpers::CalculateOnBeforeRequestDelta; |
42 using helpers::CalculateOnBeforeSendHeadersDelta; | 43 using helpers::CalculateOnBeforeSendHeadersDelta; |
43 using helpers::CalculateOnHeadersReceivedDelta; | 44 using helpers::CalculateOnHeadersReceivedDelta; |
(...skipping 22 matching lines...) Expand all Loading... | |
66 } | 67 } |
67 | 68 |
68 // Searches |key| in |collection| by iterating over its elements and returns | 69 // Searches |key| in |collection| by iterating over its elements and returns |
69 // true if found. | 70 // true if found. |
70 template <typename Collection, typename Key> | 71 template <typename Collection, typename Key> |
71 bool Contains(const Collection& collection, const Key& key) { | 72 bool Contains(const Collection& collection, const Key& key) { |
72 return std::find(collection.begin(), collection.end(), key) != | 73 return std::find(collection.begin(), collection.end(), key) != |
73 collection.end(); | 74 collection.end(); |
74 } | 75 } |
75 | 76 |
77 // Tests whether |message| is a valid ExtensionMsg_MessageInvoke, and tries | |
78 // to extract a "postData" section to be passed to onBeforeRequest listeners. | |
79 enum TestMessageResult { | |
80 kPostDataFound, | |
81 kNoPostData, | |
82 kError | |
83 }; | |
battre
2012/07/11 12:28:43
nit: newline
vabr (Chromium)
2012/07/12 15:13:11
Done.
| |
84 TestMessageResult TestMessage(IPC::Message* message, std::string* post_data) { | |
battre
2012/07/11 12:28:43
Can you rename this to something more descriptive?
vabr (Chromium)
2012/07/12 15:13:11
Done.
| |
85 if (message->type() != ExtensionMsg_MessageInvoke::ID) return kError; | |
battre
2012/07/11 12:28:43
can you move the return statements into the next l
battre
2012/07/11 12:28:43
I think all cases where you return kError are case
vabr (Chromium)
2012/07/12 15:13:11
Done. Had to move the return bool to (output) argu
vabr (Chromium)
2012/07/12 15:13:11
Done.
| |
86 ExtensionMsg_MessageInvoke::Param param; | |
87 Value* temp_value = NULL; | |
88 if (!ExtensionMsg_MessageInvoke::Read(message, ¶m)) return kError; | |
89 if (param.c.GetSize() != 2) return kError; | |
90 if (!param.c.Get(1,&temp_value)) return kError; | |
battre
2012/07/11 12:28:43
nit: space before &
vabr (Chromium)
2012/07/12 15:13:11
Done.
| |
91 std::string args; | |
92 if (!temp_value->GetAsString(&args)) return kError; | |
93 const char kPostDataHead[] = "\"postData\":{"; | |
94 size_t post_data_start = args.find(kPostDataHead); | |
95 if (post_data_start == std::string::npos) return kNoPostData; | |
96 post_data_start += sizeof(kPostDataHead) - 1; //-1 for trailing '\0' | |
battre
2012/07/11 12:28:43
nit: strlen? 2 spaces before //, 1 space after //
vabr (Chromium)
2012/07/12 15:13:11
Done.
| |
97 const size_t post_data_end = args.find("}", post_data_start); | |
98 if (post_data_end == std::string::npos) return kError; | |
99 const size_t post_data_length = (post_data_end - 1) - post_data_start; | |
100 *post_data = std::string(args, post_data_start, post_data_length); | |
101 return kPostDataFound; | |
102 } | |
103 | |
76 } // namespace | 104 } // namespace |
77 | 105 |
78 // A mock event router that responds to events with a pre-arranged queue of | 106 // A mock event router that responds to events with a pre-arranged queue of |
79 // Tasks. | 107 // Tasks. |
80 class TestIPCSender : public IPC::Sender { | 108 class TestIPCSender : public IPC::Sender { |
81 public: | 109 public: |
82 typedef std::list<linked_ptr<IPC::Message> > SentMessages; | 110 typedef std::list<linked_ptr<IPC::Message> > SentMessages; |
83 | 111 |
84 // Adds a Task to the queue. We will fire these in order as events are | 112 // Adds a Task to the queue. We will fire these in order as events are |
85 // dispatched. | 113 // dispatched. |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
391 EXPECT_TRUE(!request.is_pending()); | 419 EXPECT_TRUE(!request.is_pending()); |
392 EXPECT_EQ(net::URLRequestStatus::CANCELED, request.status().status()); | 420 EXPECT_EQ(net::URLRequestStatus::CANCELED, request.status().status()); |
393 EXPECT_EQ(net::ERR_ABORTED, request.status().error()); | 421 EXPECT_EQ(net::ERR_ABORTED, request.status().error()); |
394 EXPECT_EQ(request_url, request.url()); | 422 EXPECT_EQ(request_url, request.url()); |
395 EXPECT_EQ(1U, request.url_chain().size()); | 423 EXPECT_EQ(1U, request.url_chain().size()); |
396 EXPECT_EQ(0U, ipc_sender_.GetNumTasks()); | 424 EXPECT_EQ(0U, ipc_sender_.GetNumTasks()); |
397 | 425 |
398 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( | 426 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( |
399 &profile_, extension_id, kEventName + "/1"); | 427 &profile_, extension_id, kEventName + "/1"); |
400 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( | 428 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( |
401 &profile_, extension_id, kEventName2 + "/1"); | 429 &profile_, extension_id, kEventName2 + "/1"); |
430 } | |
431 | |
432 TEST_F(ExtensionWebRequestTest, AccessPostData) { | |
433 // We verify that POST data are accessible to OnBeforeRequest listeners. | |
434 // Construct the test data. | |
435 #define kBoundary "THIS_IS_A_BOUNDARY" | |
436 #define kMultipartBytesBlock1 "--" kBoundary "\r\n" \ | |
437 "Content-Disposition: form-data; name=\"text\"\r\n" \ | |
438 "\r\n" \ | |
439 "test text\r\n" \ | |
440 "--" kBoundary "\r\n" \ | |
441 "Content-Disposition: form-data; name=\"file\"; filename=\"test\"\r\n" \ | |
442 "Content-Type: application/octet-stream\r\n" \ | |
443 "\r\n" | |
444 #define kMultipartBytesBlock2 "\r\n" \ | |
445 "--" kBoundary "\r\n" \ | |
446 "Content-Disposition: form-data; name=\"password\"\r\n" \ | |
447 "\r\n" \ | |
448 "test password\r\n" \ | |
449 "--" kBoundary "\r\n" \ | |
450 "Content-Disposition: form-data; name=\"radio\"\r\n" \ | |
451 "\r\n" \ | |
452 "Yes\r\n" \ | |
453 "--" kBoundary "\r\n" \ | |
454 "Content-Disposition: form-data; name=\"check\"\r\n" \ | |
455 "\r\n" \ | |
456 "option A\r\n" \ | |
457 "--" kBoundary "\r\n" \ | |
458 "Content-Disposition: form-data; name=\"check\"\r\n" \ | |
459 "\r\n" \ | |
460 "option B\r\n" \ | |
461 "--" kBoundary "\r\n" \ | |
462 "Content-Disposition: form-data; name=\"txtarea\"\r\n" \ | |
463 "\r\n" \ | |
464 "Some text.\r\n" \ | |
465 "Other.\r\n" \ | |
466 "\r\n" \ | |
467 "--" kBoundary "\r\n" \ | |
468 "Content-Disposition: form-data; name=\"select\"\r\n" \ | |
469 "\r\n" \ | |
470 "one\r\n" \ | |
471 "--" kBoundary "--" | |
472 // POST data input. | |
473 const char kMultipartBytes[] = kMultipartBytesBlock1 kMultipartBytesBlock2; | |
474 const char kMultipartBytesSplit1[] = kMultipartBytesBlock1; | |
475 const char kMultipartBytesSplit2[] = kMultipartBytesBlock2; | |
476 const char kUrlEncodedBytes[] = "text=test+text&file=test-file" | |
477 "&password=test+password&radio=Yes&check=option+A&check=option+B" | |
478 "&txtarea=Some+text.%0D%0AOther.%0D%0A&select=one"; | |
479 const char kTextPlainBytes[] = "dummy text"; | |
480 // POST data output. | |
481 const char kResultMultipart[] = "\"check\":[\"option A\",\"option B\"]," \ | |
482 "\"file\":[\"test\"],\"password\":[\"test password\"]," \ | |
483 "\"radio\":[\"Yes\"],\"select\":[\"one\"],\"text\":[\"test text\"]," \ | |
484 "\"txtarea\":[\"Some text.\\r\\nOther.\\r\\n\""; | |
485 const char kResultUrlEncoded[] = "\"check\":[\"option+A\",\"option+B\"]," \ | |
486 "\"file\":[\"test-file\"],\"password\":[\"test+password\"]," \ | |
487 "\"radio\":[\"Yes\"],\"select\":[\"one\"],\"text\":[\"test+text\"]," \ | |
488 "\"txtarea\":[\"Some+text.%0D%0AOther.%0D%0A\""; | |
489 const char* kResults[] = | |
490 {kResultMultipart, kResultMultipart, kResultUrlEncoded, NULL, NULL}; | |
battre
2012/07/11 12:28:43
Rename this to kExpectedResults?
vabr (Chromium)
2012/07/12 15:13:11
Done.
| |
491 // Headers. | |
492 const char kUrlEncoded[] = "application/x-www-form-urlencoded"; | |
493 const char kTextPlain[] = "text/plain"; | |
494 const char kMultipart[] = "multipart/form-data; boundary=" kBoundary; | |
495 #undef kMultipartBytesBlock2 | |
496 #undef kMultipartBytesBlock1 | |
497 #undef kBoundary | |
498 | |
499 // Set up a dummy extension name. | |
500 ExtensionWebRequestEventRouter::RequestFilter filter; | |
501 std::string extension_id("1"); | |
502 int extra_info_spec_post = | |
503 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING | | |
504 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_POST_DATA; | |
505 int extra_info_spec_no_post = | |
506 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING; | |
507 | |
508 // Subscribe to OnBeforeRequest with POST data requirement. | |
509 const std::string kEventName(keys::kOnBeforeRequest); | |
510 base::WeakPtrFactory<TestIPCSender> ipc_sender_factory(&ipc_sender_); | |
511 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( | |
512 &profile_, extension_id, extension_id, kEventName, kEventName + "/1", | |
513 filter, extra_info_spec_post, ipc_sender_factory.GetWeakPtr()); | |
514 | |
515 // The request URL can be arbitrary but must have a HTTP or HTTPS scheme. | |
516 GURL request_url("http://www.example.com"); | |
517 | |
518 // First test: multipart POST data in one lump. | |
519 net::URLRequest request1(request_url, &delegate_, context_.get()); | |
520 request1.set_method("POST"); | |
521 request1.SetExtraRequestHeaderByName("Content-Type", kMultipart, true); | |
522 request1.AppendBytesToUpload(kMultipartBytes, strlen(kMultipartBytes)); | |
523 ipc_sender_.PushTask(base::Bind(&base::DoNothing)); | |
524 request1.Start(); | |
525 | |
526 // Second test: multipart POST data in several lumps. | |
527 net::URLRequest request2(request_url, &delegate_, context_.get()); | |
528 request2.set_method("POST"); | |
529 request2.SetExtraRequestHeaderByName("Content-Type", kMultipart, true); | |
530 request2.AppendBytesToUpload(kMultipartBytesSplit1, | |
531 strlen(kMultipartBytesSplit1)); | |
532 request2.AppendBytesToUpload(kMultipartBytesSplit2, | |
533 strlen(kMultipartBytesSplit2)); | |
534 ipc_sender_.PushTask(base::Bind(&base::DoNothing)); | |
535 request2.Start(); | |
536 | |
537 // Third test: URL-encoded POST data. | |
538 net::URLRequest request3(request_url, &delegate_, context_.get()); | |
539 request3.set_method("POST"); | |
540 request3.SetExtraRequestHeaderByName("Content-Type", kUrlEncoded, true); | |
541 request3.AppendBytesToUpload(kUrlEncodedBytes, strlen(kUrlEncodedBytes)); | |
542 ipc_sender_.PushTask(base::Bind(&base::DoNothing)); | |
543 request3.Start(); | |
544 | |
545 // Fourth test: text/plain POST data in one lump. | |
546 net::URLRequest request4(request_url, &delegate_, context_.get()); | |
547 request4.set_method("POST"); | |
548 request4.SetExtraRequestHeaderByName("Content-Type", kTextPlain, true); | |
549 request4.AppendBytesToUpload(kTextPlainBytes, strlen(kTextPlainBytes)); | |
550 ipc_sender_.PushTask(base::Bind(&base::DoNothing)); | |
551 request4.Start(); | |
552 | |
553 MessageLoop::current()->RunAllPending(); | |
554 | |
555 // Now remove the requirement of POST data. | |
556 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( | |
557 &profile_, extension_id, kEventName + "/1"); | |
558 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( | |
559 &profile_, extension_id, extension_id, kEventName, kEventName + "/1", | |
560 filter, extra_info_spec_no_post, ipc_sender_factory.GetWeakPtr()); | |
561 | |
562 // Fifth test is the same as the first. Nobody asked for POST data, | |
563 // so in this case, none should be reported. | |
564 net::URLRequest request5(request_url, &delegate_, context_.get()); | |
565 request5.set_method("POST"); | |
566 request5.SetExtraRequestHeaderByName("Content-Type", kMultipart, true); | |
567 request5.AppendBytesToUpload(kMultipartBytes, strlen(kMultipartBytes)); | |
568 ipc_sender_.PushTask(base::Bind(&base::DoNothing)); | |
569 request5.Start(); | |
570 | |
571 MessageLoop::current()->RunAllPending(); | |
572 | |
573 IPC::Message* message = NULL; | |
574 std::string post_data; | |
575 TestIPCSender::SentMessages::const_iterator i = ipc_sender_.sent_begin(); | |
576 for (size_t test = 0; test < arraysize(kResults); ++test) { | |
577 EXPECT_FALSE(i == ipc_sender_.sent_end()); | |
battre
2012/07/11 12:28:43
does EXPECT_NE work? Otherwise, I think it is simp
vabr (Chromium)
2012/07/12 15:13:11
Done.
| |
578 message = (i++)->get(); | |
579 if (kResults[test] == NULL) { | |
580 EXPECT_EQ(kNoPostData, TestMessage(message, &post_data)); | |
581 } else { | |
582 EXPECT_EQ(kPostDataFound, TestMessage(message, &post_data)); | |
583 EXPECT_EQ(kResults[test], post_data); | |
584 } | |
585 } | |
586 | |
587 EXPECT_TRUE(i == ipc_sender_.sent_end()); | |
588 | |
589 // Clean-up. | |
590 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( | |
591 &profile_, extension_id, kEventName + "/1"); | |
402 } | 592 } |
403 | 593 |
404 struct HeaderModificationTest_Header { | 594 struct HeaderModificationTest_Header { |
405 const char* name; | 595 const char* name; |
406 const char* value; | 596 const char* value; |
407 }; | 597 }; |
408 | 598 |
409 struct HeaderModificationTest_Modification { | 599 struct HeaderModificationTest_Modification { |
410 enum Type { | 600 enum Type { |
411 SET, | 601 SET, |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
656 true, | 846 true, |
657 ExtensionWebRequestEventRouter::ExtraInfoSpec::RESPONSE_HEADERS); | 847 ExtensionWebRequestEventRouter::ExtraInfoSpec::RESPONSE_HEADERS); |
658 TestInitFromValue( | 848 TestInitFromValue( |
659 "blocking", | 849 "blocking", |
660 true, | 850 true, |
661 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING); | 851 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING); |
662 TestInitFromValue( | 852 TestInitFromValue( |
663 "asyncBlocking", | 853 "asyncBlocking", |
664 true, | 854 true, |
665 ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING); | 855 ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING); |
856 TestInitFromValue( | |
857 "requestPostData", | |
858 true, | |
859 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_POST_DATA); | |
666 | 860 |
667 // Multiple valid values are bitwise-or'ed. | 861 // Multiple valid values are bitwise-or'ed. |
668 TestInitFromValue( | 862 TestInitFromValue( |
669 "requestHeaders,blocking", | 863 "requestHeaders,blocking", |
670 true, | 864 true, |
671 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS | | 865 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS | |
672 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING); | 866 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING); |
673 | 867 |
674 // Any invalid values lead to a bad parse. | 868 // Any invalid values lead to a bad parse. |
675 TestInitFromValue("invalidValue", false, 0); | 869 TestInitFromValue("invalidValue", false, 0); |
(...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1510 }; | 1704 }; |
1511 for (size_t i = 0; i < arraysize(sensitive_urls); ++i) { | 1705 for (size_t i = 0; i < arraysize(sensitive_urls); ++i) { |
1512 EXPECT_TRUE(helpers::HideRequestForURL(GURL(sensitive_urls[i]))) | 1706 EXPECT_TRUE(helpers::HideRequestForURL(GURL(sensitive_urls[i]))) |
1513 << sensitive_urls[i]; | 1707 << sensitive_urls[i]; |
1514 } | 1708 } |
1515 for (size_t i = 0; i < arraysize(non_sensitive_urls); ++i) { | 1709 for (size_t i = 0; i < arraysize(non_sensitive_urls); ++i) { |
1516 EXPECT_FALSE(helpers::HideRequestForURL(GURL(non_sensitive_urls[i]))) | 1710 EXPECT_FALSE(helpers::HideRequestForURL(GURL(non_sensitive_urls[i]))) |
1517 << non_sensitive_urls[i]; | 1711 << non_sensitive_urls[i]; |
1518 } | 1712 } |
1519 } | 1713 } |
OLD | NEW |