Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: chrome/browser/extensions/api/web_request/web_request_api_unittest.cc

Issue 10694055: Add read-only access to POST data for webRequest's onBeforeRequest (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Typo fixed Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 // Inspects the data attached to the |message| and tries to extract its
78 // "postData" section into |post_data|.
79 void GetPostData(IPC::Message* message, std::string* post_data, bool* success) {
80 ASSERT_TRUE(success != NULL);
81 *success = false;
82 ASSERT_EQ(message->type(), ExtensionMsg_MessageInvoke::ID);
83 ExtensionMsg_MessageInvoke::Param param;
84 Value* temp_value = NULL;
85 ASSERT_TRUE(ExtensionMsg_MessageInvoke::Read(message, &param));
86 ASSERT_GE(param.c.GetSize(), static_cast<size_t>(2));
87 ASSERT_TRUE(param.c.Get(1, &temp_value));
88 std::string args;
89 ASSERT_TRUE(temp_value->GetAsString(&args));
90 const char kPostDataHead[] = "\"postData\":{";
91 size_t post_data_start = args.find(kPostDataHead);
92 if (post_data_start == std::string::npos)
93 return;
94 post_data_start += strlen(kPostDataHead);
95 const size_t post_data_end = args.find("}", post_data_start);
96 ASSERT_NE(post_data_end, std::string::npos);
97 const size_t post_data_length = (post_data_end - 1) - post_data_start;
98 *post_data = std::string(args, post_data_start, post_data_length);
99 *success = true;
100 return;
101 }
102
76 } // namespace 103 } // namespace
77 104
78 // A mock event router that responds to events with a pre-arranged queue of 105 // A mock event router that responds to events with a pre-arranged queue of
79 // Tasks. 106 // Tasks.
80 class TestIPCSender : public IPC::Sender { 107 class TestIPCSender : public IPC::Sender {
81 public: 108 public:
82 typedef std::list<linked_ptr<IPC::Message> > SentMessages; 109 typedef std::list<linked_ptr<IPC::Message> > SentMessages;
83 110
84 // Adds a Task to the queue. We will fire these in order as events are 111 // Adds a Task to the queue. We will fire these in order as events are
85 // dispatched. 112 // dispatched.
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 EXPECT_TRUE(!request.is_pending()); 418 EXPECT_TRUE(!request.is_pending());
392 EXPECT_EQ(net::URLRequestStatus::CANCELED, request.status().status()); 419 EXPECT_EQ(net::URLRequestStatus::CANCELED, request.status().status());
393 EXPECT_EQ(net::ERR_ABORTED, request.status().error()); 420 EXPECT_EQ(net::ERR_ABORTED, request.status().error());
394 EXPECT_EQ(request_url, request.url()); 421 EXPECT_EQ(request_url, request.url());
395 EXPECT_EQ(1U, request.url_chain().size()); 422 EXPECT_EQ(1U, request.url_chain().size());
396 EXPECT_EQ(0U, ipc_sender_.GetNumTasks()); 423 EXPECT_EQ(0U, ipc_sender_.GetNumTasks());
397 424
398 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( 425 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
399 &profile_, extension_id, kEventName + "/1"); 426 &profile_, extension_id, kEventName + "/1");
400 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( 427 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
401 &profile_, extension_id, kEventName2 + "/1"); 428 &profile_, extension_id, kEventName2 + "/1");
429 }
430
431 TEST_F(ExtensionWebRequestTest, AccessPostData) {
battre 2012/07/13 15:20:04 What do you think of moving most of this to post_d
vabr (Chromium) 2012/07/16 15:40:51 Done.
432 // We verify that POST data are accessible to OnBeforeRequest listeners.
433 // Construct the test data.
434 #define kBoundary "THIS_IS_A_BOUNDARY"
435 #define kMultipartBytesBlock1 "--" kBoundary "\r\n" \
436 "Content-Disposition: form-data; name=\"text\"\r\n" \
437 "\r\n" \
438 "test text\r\n" \
439 "--" kBoundary "\r\n" \
440 "Content-Disposition: form-data; name=\"file\"; filename=\"test\"\r\n" \
441 "Content-Type: application/octet-stream\r\n" \
442 "\r\n"
443 #define kMultipartBytesBlock2 "\r\n" \
444 "--" kBoundary "\r\n" \
445 "Content-Disposition: form-data; name=\"password\"\r\n" \
446 "\r\n" \
447 "test password\r\n" \
448 "--" kBoundary "\r\n" \
449 "Content-Disposition: form-data; name=\"radio\"\r\n" \
450 "\r\n" \
451 "Yes\r\n" \
452 "--" kBoundary "\r\n" \
453 "Content-Disposition: form-data; name=\"check\"\r\n" \
454 "\r\n" \
455 "option A\r\n" \
456 "--" kBoundary "\r\n" \
457 "Content-Disposition: form-data; name=\"check\"\r\n" \
458 "\r\n" \
459 "option B\r\n" \
460 "--" kBoundary "\r\n" \
461 "Content-Disposition: form-data; name=\"txtarea\"\r\n" \
462 "\r\n" \
463 "Some text.\r\n" \
464 "Other.\r\n" \
465 "\r\n" \
466 "--" kBoundary "\r\n" \
467 "Content-Disposition: form-data; name=\"select\"\r\n" \
468 "\r\n" \
469 "one\r\n" \
470 "--" kBoundary "--"
471 // POST data input.
472 const char kMultipartBytes[] = kMultipartBytesBlock1 kMultipartBytesBlock2;
473 const char kMultipartBytesSplit1[] = kMultipartBytesBlock1;
474 const char kMultipartBytesSplit2[] = kMultipartBytesBlock2;
475 const char kUrlEncodedBytes[] = "text=test+text&file=test"
476 "&password=test+password&radio=Yes&check=option+A&check=option+B"
477 "&txtarea=Some+text.%0D%0AOther.%0D%0A&select=one";
478 const char kTextPlainBytes[] = "dummy text";
479 // POST data output.
480 const char kResultString[] = "\"check\":[\"option A\",\"option B\"]," \
481 "\"file\":[\"test\"],\"password\":[\"test password\"]," \
482 "\"radio\":[\"Yes\"],\"select\":[\"one\"],\"text\":[\"test text\"]," \
483 "\"txtarea\":[\"Some text.\\r\\nOther.\\r\\n\"";
484 bool kResultExpected[] = {true, true, true, false, false};
485 // Headers.
486 const char kUrlEncoded[] = "application/x-www-form-urlencoded";
487 const char kTextPlain[] = "text/plain";
488 const char kMultipart[] = "multipart/form-data; boundary=" kBoundary;
489 #undef kMultipartBytesBlock2
490 #undef kMultipartBytesBlock1
491 #undef kBoundary
492
493 // Set up a dummy extension name.
494 ExtensionWebRequestEventRouter::RequestFilter filter;
495 std::string extension_id("1");
496 int extra_info_spec_post =
497 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING |
498 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_POST_DATA;
499 int extra_info_spec_no_post =
500 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING;
501
502 // Subscribe to OnBeforeRequest with POST data requirement.
503 const std::string kEventName(keys::kOnBeforeRequest);
504 base::WeakPtrFactory<TestIPCSender> ipc_sender_factory(&ipc_sender_);
505 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
506 &profile_, extension_id, extension_id, kEventName, kEventName + "/1",
507 filter, extra_info_spec_post, ipc_sender_factory.GetWeakPtr());
508
509 // The request URL can be arbitrary but must have a HTTP or HTTPS scheme.
510 GURL request_url("http://www.example.com");
511
512 // First test: multipart POST data in one lump.
513 net::URLRequest request1(request_url, &delegate_, context_.get());
514 request1.set_method("POST");
515 request1.SetExtraRequestHeaderByName("Content-Type", kMultipart, true);
516 request1.AppendBytesToUpload(kMultipartBytes, strlen(kMultipartBytes));
517 ipc_sender_.PushTask(base::Bind(&base::DoNothing));
518 request1.Start();
519
520 // Second test: multipart POST data in several lumps.
521 net::URLRequest request2(request_url, &delegate_, context_.get());
522 request2.set_method("POST");
523 request2.SetExtraRequestHeaderByName("Content-Type", kMultipart, true);
524 request2.AppendBytesToUpload(kMultipartBytesSplit1,
525 strlen(kMultipartBytesSplit1));
526 request2.AppendBytesToUpload(kMultipartBytesSplit2,
527 strlen(kMultipartBytesSplit2));
528 ipc_sender_.PushTask(base::Bind(&base::DoNothing));
529 request2.Start();
530
531 // Third test: URL-encoded POST data.
532 net::URLRequest request3(request_url, &delegate_, context_.get());
533 request3.set_method("POST");
534 request3.SetExtraRequestHeaderByName("Content-Type", kUrlEncoded, true);
535 request3.AppendBytesToUpload(kUrlEncodedBytes, strlen(kUrlEncodedBytes));
536 ipc_sender_.PushTask(base::Bind(&base::DoNothing));
537 request3.Start();
538
539 // Fourth test: text/plain POST data in one lump.
540 net::URLRequest request4(request_url, &delegate_, context_.get());
541 request4.set_method("POST");
542 request4.SetExtraRequestHeaderByName("Content-Type", kTextPlain, true);
543 request4.AppendBytesToUpload(kTextPlainBytes, strlen(kTextPlainBytes));
544 ipc_sender_.PushTask(base::Bind(&base::DoNothing));
545 request4.Start();
546
547 MessageLoop::current()->RunAllPending();
548
549 // Now remove the requirement of POST data.
550 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
551 &profile_, extension_id, kEventName + "/1");
552 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
553 &profile_, extension_id, extension_id, kEventName, kEventName + "/1",
554 filter, extra_info_spec_no_post, ipc_sender_factory.GetWeakPtr());
555
556 // Fifth test is the same as the first. Nobody asked for POST data,
557 // so in this case, none should be reported.
558 net::URLRequest request5(request_url, &delegate_, context_.get());
559 request5.set_method("POST");
560 request5.SetExtraRequestHeaderByName("Content-Type", kMultipart, true);
561 request5.AppendBytesToUpload(kMultipartBytes, strlen(kMultipartBytes));
562 ipc_sender_.PushTask(base::Bind(&base::DoNothing));
563 request5.Start();
564
565 MessageLoop::current()->RunAllPending();
566
567 IPC::Message* message = NULL;
568 std::string post_data;
569 TestIPCSender::SentMessages::const_iterator i = ipc_sender_.sent_begin();
570 for (size_t test = 0; test < arraysize(kResultExpected); ++test) {
571 EXPECT_NE(i, ipc_sender_.sent_end());
572 message = (i++)->get();
573 bool post_data_found;
574 GetPostData(message, &post_data, &post_data_found);
575 if (kResultExpected[test]) {
576 EXPECT_TRUE(post_data_found);
577 EXPECT_EQ(kResultString, post_data);
578 } else {
579 EXPECT_FALSE(post_data_found);
580 }
581 }
582
583 EXPECT_TRUE(i == ipc_sender_.sent_end());
584
585 // Clean-up.
586 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
587 &profile_, extension_id, kEventName + "/1");
402 } 588 }
403 589
404 struct HeaderModificationTest_Header { 590 struct HeaderModificationTest_Header {
405 const char* name; 591 const char* name;
406 const char* value; 592 const char* value;
407 }; 593 };
408 594
409 struct HeaderModificationTest_Modification { 595 struct HeaderModificationTest_Modification {
410 enum Type { 596 enum Type {
411 SET, 597 SET,
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 true, 842 true,
657 ExtensionWebRequestEventRouter::ExtraInfoSpec::RESPONSE_HEADERS); 843 ExtensionWebRequestEventRouter::ExtraInfoSpec::RESPONSE_HEADERS);
658 TestInitFromValue( 844 TestInitFromValue(
659 "blocking", 845 "blocking",
660 true, 846 true,
661 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING); 847 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING);
662 TestInitFromValue( 848 TestInitFromValue(
663 "asyncBlocking", 849 "asyncBlocking",
664 true, 850 true,
665 ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING); 851 ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING);
852 TestInitFromValue(
853 "requestPostData",
854 true,
855 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_POST_DATA);
666 856
667 // Multiple valid values are bitwise-or'ed. 857 // Multiple valid values are bitwise-or'ed.
668 TestInitFromValue( 858 TestInitFromValue(
669 "requestHeaders,blocking", 859 "requestHeaders,blocking",
670 true, 860 true,
671 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS | 861 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS |
672 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING); 862 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING);
673 863
674 // Any invalid values lead to a bad parse. 864 // Any invalid values lead to a bad parse.
675 TestInitFromValue("invalidValue", false, 0); 865 TestInitFromValue("invalidValue", false, 0);
(...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after
1525 // Check that requests are rejected if their first party url is sensitive. 1715 // Check that requests are rejected if their first party url is sensitive.
1526 ASSERT_GE(arraysize(non_sensitive_urls), 1u); 1716 ASSERT_GE(arraysize(non_sensitive_urls), 1u);
1527 GURL non_sensitive_url(non_sensitive_urls[0]); 1717 GURL non_sensitive_url(non_sensitive_urls[0]);
1528 for (size_t i = 0; i < arraysize(sensitive_urls); ++i) { 1718 for (size_t i = 0; i < arraysize(sensitive_urls); ++i) {
1529 TestURLRequest request(non_sensitive_url, NULL, &context); 1719 TestURLRequest request(non_sensitive_url, NULL, &context);
1530 GURL sensitive_url(sensitive_urls[i]); 1720 GURL sensitive_url(sensitive_urls[i]);
1531 request.set_first_party_for_cookies(sensitive_url); 1721 request.set_first_party_for_cookies(sensitive_url);
1532 EXPECT_TRUE(helpers::HideRequest(&request)) << sensitive_urls[i]; 1722 EXPECT_TRUE(helpers::HideRequest(&request)) << sensitive_urls[i];
1533 } 1723 }
1534 } 1724 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698