| 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 } | 66 } |
| 67 | 67 |
| 68 // Searches |key| in |collection| by iterating over its elements and returns | 68 // Searches |key| in |collection| by iterating over its elements and returns |
| 69 // true if found. | 69 // true if found. |
| 70 template <typename Collection, typename Key> | 70 template <typename Collection, typename Key> |
| 71 bool Contains(const Collection& collection, const Key& key) { | 71 bool Contains(const Collection& collection, const Key& key) { |
| 72 return std::find(collection.begin(), collection.end(), key) != | 72 return std::find(collection.begin(), collection.end(), key) != |
| 73 collection.end(); | 73 collection.end(); |
| 74 } | 74 } |
| 75 | 75 |
| 76 // Inspects the data attached to the |message| and tries to extract its |
| 77 // "keys::kFormDataKey" section into |form_data|. Returns true on success. |
| 78 bool GetFormData(IPC::Message* message, std::string* form_data) { |
| 79 CHECK(message->type() == ExtensionMsg_MessageInvoke::ID); |
| 80 ExtensionMsg_MessageInvoke::Param param; |
| 81 Value* temp_value = NULL; |
| 82 CHECK(ExtensionMsg_MessageInvoke::Read(message, ¶m)); |
| 83 CHECK(param.c.GetSize() >= 2); |
| 84 CHECK(param.c.Get(1, &temp_value)); |
| 85 std::string args; |
| 86 CHECK(temp_value->GetAsString(&args)); |
| 87 |
| 88 const std::string kFormDataHead( |
| 89 std::string("\"") + keys::kFormDataKey + "\":{"); |
| 90 size_t form_data_start = args.find(kFormDataHead); |
| 91 if (form_data_start == std::string::npos) |
| 92 return false; |
| 93 form_data_start += kFormDataHead.size(); |
| 94 |
| 95 const size_t form_data_end = args.find("}", form_data_start); |
| 96 CHECK(form_data_end != std::string::npos); |
| 97 const size_t form_data_length = form_data_end - form_data_start; |
| 98 *form_data = std::string(args, form_data_start, form_data_length); |
| 99 return true; |
| 100 } |
| 101 |
| 76 } // namespace | 102 } // namespace |
| 77 | 103 |
| 78 // A mock event router that responds to events with a pre-arranged queue of | 104 // A mock event router that responds to events with a pre-arranged queue of |
| 79 // Tasks. | 105 // Tasks. |
| 80 class TestIPCSender : public IPC::Sender { | 106 class TestIPCSender : public IPC::Sender { |
| 81 public: | 107 public: |
| 82 typedef std::list<linked_ptr<IPC::Message> > SentMessages; | 108 typedef std::list<linked_ptr<IPC::Message> > SentMessages; |
| 83 | 109 |
| 84 // Adds a Task to the queue. We will fire these in order as events are | 110 // Adds a Task to the queue. We will fire these in order as events are |
| 85 // dispatched. | 111 // dispatched. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 enable_referrers_.Init( | 152 enable_referrers_.Init( |
| 127 prefs::kEnableReferrers, profile_.GetTestingPrefService(), NULL); | 153 prefs::kEnableReferrers, profile_.GetTestingPrefService(), NULL); |
| 128 network_delegate_.reset(new ChromeNetworkDelegate( | 154 network_delegate_.reset(new ChromeNetworkDelegate( |
| 129 event_router_.get(), NULL, NULL, &profile_, | 155 event_router_.get(), NULL, NULL, &profile_, |
| 130 CookieSettings::Factory::GetForProfile(&profile_), &enable_referrers_)); | 156 CookieSettings::Factory::GetForProfile(&profile_), &enable_referrers_)); |
| 131 context_.reset(new TestURLRequestContext(true)); | 157 context_.reset(new TestURLRequestContext(true)); |
| 132 context_->set_network_delegate(network_delegate_.get()); | 158 context_->set_network_delegate(network_delegate_.get()); |
| 133 context_->Init(); | 159 context_->Init(); |
| 134 } | 160 } |
| 135 | 161 |
| 162 // Fires a URLRequest with the specified |content_type|. Method will be "POST" |
| 163 // and the data will be |bytes|. |
| 164 void FireURLRequestWithPostData(const char* content_type, const char* bytes); |
| 165 |
| 136 MessageLoopForIO message_loop_; | 166 MessageLoopForIO message_loop_; |
| 137 content::TestBrowserThread ui_thread_; | 167 content::TestBrowserThread ui_thread_; |
| 138 content::TestBrowserThread io_thread_; | 168 content::TestBrowserThread io_thread_; |
| 139 TestingProfile profile_; | 169 TestingProfile profile_; |
| 140 TestDelegate delegate_; | 170 TestDelegate delegate_; |
| 141 BooleanPrefMember enable_referrers_; | 171 BooleanPrefMember enable_referrers_; |
| 142 TestIPCSender ipc_sender_; | 172 TestIPCSender ipc_sender_; |
| 143 scoped_refptr<ExtensionEventRouterForwarder> event_router_; | 173 scoped_refptr<ExtensionEventRouterForwarder> event_router_; |
| 144 scoped_refptr<ExtensionInfoMap> extension_info_map_; | 174 scoped_refptr<ExtensionInfoMap> extension_info_map_; |
| 145 scoped_ptr<ChromeNetworkDelegate> network_delegate_; | 175 scoped_ptr<ChromeNetworkDelegate> network_delegate_; |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 EXPECT_TRUE(!request.is_pending()); | 421 EXPECT_TRUE(!request.is_pending()); |
| 392 EXPECT_EQ(net::URLRequestStatus::CANCELED, request.status().status()); | 422 EXPECT_EQ(net::URLRequestStatus::CANCELED, request.status().status()); |
| 393 EXPECT_EQ(net::ERR_ABORTED, request.status().error()); | 423 EXPECT_EQ(net::ERR_ABORTED, request.status().error()); |
| 394 EXPECT_EQ(request_url, request.url()); | 424 EXPECT_EQ(request_url, request.url()); |
| 395 EXPECT_EQ(1U, request.url_chain().size()); | 425 EXPECT_EQ(1U, request.url_chain().size()); |
| 396 EXPECT_EQ(0U, ipc_sender_.GetNumTasks()); | 426 EXPECT_EQ(0U, ipc_sender_.GetNumTasks()); |
| 397 | 427 |
| 398 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( | 428 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( |
| 399 &profile_, extension_id, kEventName + "/1"); | 429 &profile_, extension_id, kEventName + "/1"); |
| 400 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( | 430 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( |
| 401 &profile_, extension_id, kEventName2 + "/1"); | 431 &profile_, extension_id, kEventName2 + "/1"); |
| 432 } |
| 433 |
| 434 void ExtensionWebRequestTest::FireURLRequestWithPostData( |
| 435 const char* content_type, |
| 436 const char* bytes) { |
| 437 // The request URL can be arbitrary but must have an HTTP or HTTPS scheme. |
| 438 GURL request_url("http://www.example.com"); |
| 439 net::URLRequest request(request_url, &delegate_, context_.get()); |
| 440 request.set_method("POST"); |
| 441 request.SetExtraRequestHeaderByName("Content-Type", content_type, true); |
| 442 request.AppendBytesToUpload(bytes, strlen(bytes)); |
| 443 ipc_sender_.PushTask(base::Bind(&base::DoNothing)); |
| 444 request.Start(); |
| 445 } |
| 446 |
| 447 TEST_F(ExtensionWebRequestTest, AccessPostData) { |
| 448 // We verify that POST data are accessible to OnBeforeRequest listeners. |
| 449 // Construct the test data. |
| 450 #define kBoundary "THIS_IS_A_BOUNDARY" |
| 451 #define kBlock "--" kBoundary "\r\n" \ |
| 452 "Content-Disposition: form-data; name=\"text\"\r\n" \ |
| 453 "\r\n" \ |
| 454 "test text\r\n" \ |
| 455 "--" kBoundary "--" |
| 456 // POST data input. |
| 457 const char kMultipartBytes[] = kBlock; |
| 458 // POST data output. |
| 459 const char kResultString[] = "\"text\":[\"test text\"]"; |
| 460 // Header. |
| 461 const char kMultipart[] = "multipart/form-data; boundary=" kBoundary; |
| 462 #undef kBlock |
| 463 #undef kBoundary |
| 464 bool kSuccessExpected[] = {true, false}; |
| 465 |
| 466 // Set up a dummy extension name. |
| 467 ExtensionWebRequestEventRouter::RequestFilter filter; |
| 468 std::string extension_id("1"); |
| 469 int extra_info_spec_post = |
| 470 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING | |
| 471 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_POST_DATA; |
| 472 int extra_info_spec_no_post = |
| 473 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING; |
| 474 |
| 475 // Subscribe to OnBeforeRequest with POST data requirement. |
| 476 const std::string kEventName(keys::kOnBeforeRequest); |
| 477 base::WeakPtrFactory<TestIPCSender> ipc_sender_factory(&ipc_sender_); |
| 478 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( |
| 479 &profile_, extension_id, extension_id, kEventName, kEventName + "/1", |
| 480 filter, extra_info_spec_post, ipc_sender_factory.GetWeakPtr()); |
| 481 |
| 482 FireURLRequestWithPostData(kMultipart, kMultipartBytes); |
| 483 |
| 484 MessageLoop::current()->RunAllPending(); |
| 485 |
| 486 // Now remove the requirement of POST data. |
| 487 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( |
| 488 &profile_, extension_id, kEventName + "/1"); |
| 489 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( |
| 490 &profile_, extension_id, extension_id, kEventName, kEventName + "/1", |
| 491 filter, extra_info_spec_no_post, ipc_sender_factory.GetWeakPtr()); |
| 492 |
| 493 FireURLRequestWithPostData(kMultipart, kMultipartBytes); |
| 494 |
| 495 MessageLoop::current()->RunAllPending(); |
| 496 |
| 497 IPC::Message* message = NULL; |
| 498 std::string form_data; |
| 499 TestIPCSender::SentMessages::const_iterator i = ipc_sender_.sent_begin(); |
| 500 for (size_t test = 0; test < arraysize(kSuccessExpected); ++test) { |
| 501 EXPECT_NE(i, ipc_sender_.sent_end()); |
| 502 message = (i++)->get(); |
| 503 if (kSuccessExpected[test]) { |
| 504 EXPECT_TRUE(GetFormData(message, &form_data)) << test; |
| 505 EXPECT_EQ(kResultString, form_data); |
| 506 } else { |
| 507 EXPECT_FALSE(GetFormData(message, &form_data)); |
| 508 } |
| 509 } |
| 510 |
| 511 EXPECT_EQ(i, ipc_sender_.sent_end()); |
| 512 |
| 513 // Clean-up. |
| 514 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( |
| 515 &profile_, extension_id, kEventName + "/1"); |
| 402 } | 516 } |
| 403 | 517 |
| 404 struct HeaderModificationTest_Header { | 518 struct HeaderModificationTest_Header { |
| 405 const char* name; | 519 const char* name; |
| 406 const char* value; | 520 const char* value; |
| 407 }; | 521 }; |
| 408 | 522 |
| 409 struct HeaderModificationTest_Modification { | 523 struct HeaderModificationTest_Modification { |
| 410 enum Type { | 524 enum Type { |
| 411 SET, | 525 SET, |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 true, | 770 true, |
| 657 ExtensionWebRequestEventRouter::ExtraInfoSpec::RESPONSE_HEADERS); | 771 ExtensionWebRequestEventRouter::ExtraInfoSpec::RESPONSE_HEADERS); |
| 658 TestInitFromValue( | 772 TestInitFromValue( |
| 659 "blocking", | 773 "blocking", |
| 660 true, | 774 true, |
| 661 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING); | 775 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING); |
| 662 TestInitFromValue( | 776 TestInitFromValue( |
| 663 "asyncBlocking", | 777 "asyncBlocking", |
| 664 true, | 778 true, |
| 665 ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING); | 779 ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING); |
| 780 TestInitFromValue( |
| 781 "requestPostData", |
| 782 true, |
| 783 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_POST_DATA); |
| 666 | 784 |
| 667 // Multiple valid values are bitwise-or'ed. | 785 // Multiple valid values are bitwise-or'ed. |
| 668 TestInitFromValue( | 786 TestInitFromValue( |
| 669 "requestHeaders,blocking", | 787 "requestHeaders,blocking", |
| 670 true, | 788 true, |
| 671 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS | | 789 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS | |
| 672 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING); | 790 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING); |
| 673 | 791 |
| 674 // Any invalid values lead to a bad parse. | 792 // Any invalid values lead to a bad parse. |
| 675 TestInitFromValue("invalidValue", false, 0); | 793 TestInitFromValue("invalidValue", false, 0); |
| (...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1525 // Check that requests are rejected if their first party url is sensitive. | 1643 // Check that requests are rejected if their first party url is sensitive. |
| 1526 ASSERT_GE(arraysize(non_sensitive_urls), 1u); | 1644 ASSERT_GE(arraysize(non_sensitive_urls), 1u); |
| 1527 GURL non_sensitive_url(non_sensitive_urls[0]); | 1645 GURL non_sensitive_url(non_sensitive_urls[0]); |
| 1528 for (size_t i = 0; i < arraysize(sensitive_urls); ++i) { | 1646 for (size_t i = 0; i < arraysize(sensitive_urls); ++i) { |
| 1529 TestURLRequest request(non_sensitive_url, NULL, &context); | 1647 TestURLRequest request(non_sensitive_url, NULL, &context); |
| 1530 GURL sensitive_url(sensitive_urls[i]); | 1648 GURL sensitive_url(sensitive_urls[i]); |
| 1531 request.set_first_party_for_cookies(sensitive_url); | 1649 request.set_first_party_for_cookies(sensitive_url); |
| 1532 EXPECT_TRUE(helpers::HideRequest(&request)) << sensitive_urls[i]; | 1650 EXPECT_TRUE(helpers::HideRequest(&request)) << sensitive_urls[i]; |
| 1533 } | 1651 } |
| 1534 } | 1652 } |
| OLD | NEW |