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

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: 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 // 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 {kPostDataFound, kNoPostData, kError};
battre 2012/07/06 07:36:24 style: enum TestMessageResult { kPostDataFound,
vabr (Chromium) 2012/07/06 14:09:01 Done.
80 TestMessageResult TestMessage(IPC::Message* message, std::string* post_data) {
81 if (message->type() != ExtensionMsg_MessageInvoke::ID) return kError;
82 ExtensionMsg_MessageInvoke::Param param;
83 Value* temp_value = NULL;
84 if (!ExtensionMsg_MessageInvoke::Read(message, &param)) return kError;
85 if (param.c.GetSize() != 2) return kError;
86 if (!param.c.Get(1,&temp_value)) return kError;
87 std::string args;
88 if (!temp_value->GetAsString(&args)) return kError;
89 const char kPostDataHead[] = "\"postData\":{";
90 size_t post_data_start = args.find(kPostDataHead);
91 if (post_data_start == std::string::npos) return kNoPostData;
92 post_data_start += sizeof(kPostDataHead) - 1; //-1 for trailing '\0'
93 const size_t post_data_end = args.find("}", post_data_start);
94 if (post_data_end == std::string::npos) return kError;
95 const size_t post_data_length = (post_data_end - 1) - post_data_start;
96 *post_data = std::string(args, post_data_start, post_data_length);
97 return kPostDataFound;
98 }
99
76 } // namespace 100 } // namespace
77 101
78 // A mock event router that responds to events with a pre-arranged queue of 102 // A mock event router that responds to events with a pre-arranged queue of
79 // Tasks. 103 // Tasks.
80 class TestIPCSender : public IPC::Sender { 104 class TestIPCSender : public IPC::Sender {
81 public: 105 public:
82 typedef std::list<linked_ptr<IPC::Message> > SentMessages; 106 typedef std::list<linked_ptr<IPC::Message> > SentMessages;
83 107
84 // Adds a Task to the queue. We will fire these in order as events are 108 // Adds a Task to the queue. We will fire these in order as events are
85 // dispatched. 109 // dispatched.
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 EXPECT_TRUE(!request.is_pending()); 415 EXPECT_TRUE(!request.is_pending());
392 EXPECT_EQ(net::URLRequestStatus::CANCELED, request.status().status()); 416 EXPECT_EQ(net::URLRequestStatus::CANCELED, request.status().status());
393 EXPECT_EQ(net::ERR_ABORTED, request.status().error()); 417 EXPECT_EQ(net::ERR_ABORTED, request.status().error());
394 EXPECT_EQ(request_url, request.url()); 418 EXPECT_EQ(request_url, request.url());
395 EXPECT_EQ(1U, request.url_chain().size()); 419 EXPECT_EQ(1U, request.url_chain().size());
396 EXPECT_EQ(0U, ipc_sender_.GetNumTasks()); 420 EXPECT_EQ(0U, ipc_sender_.GetNumTasks());
397 421
398 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( 422 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
399 &profile_, extension_id, kEventName + "/1"); 423 &profile_, extension_id, kEventName + "/1");
400 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( 424 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
401 &profile_, extension_id, kEventName2 + "/1"); 425 &profile_, extension_id, kEventName2 + "/1");
426 }
427
428 TEST_F(ExtensionWebRequestTest, AccessPostData) {
429 // We verify that POST data are accessible to OnBeforeRequest listeners.
430 // Construct the test data.
431 #define kBoundary "THIS_IS_A_BOUNDARY"
432 #define kMultipartBytesBlock1 "--" kBoundary "\r\n" \
433 "Content-Disposition: form-data; name=\"text\"\r\n" \
434 "\r\n" \
435 "test text\r\n" \
436 "--" kBoundary "\r\n" \
437 "Content-Disposition: form-data; name=\"file\"; filename=\"test\"\r\n" \
438 "Content-Type: application/octet-stream\r\n" \
439 "\r\n"
440 #define kMultipartBytesBlock2 "\r\n" \
441 "--" kBoundary "\r\n" \
442 "Content-Disposition: form-data; name=\"password\"\r\n" \
443 "\r\n" \
444 "test password\r\n" \
445 "--" kBoundary "\r\n" \
446 "Content-Disposition: form-data; name=\"radio\"\r\n" \
447 "\r\n" \
448 "Yes\r\n" \
449 "--" kBoundary "\r\n" \
450 "Content-Disposition: form-data; name=\"check\"\r\n" \
451 "\r\n" \
452 "option A\r\n" \
453 "--" kBoundary "\r\n" \
454 "Content-Disposition: form-data; name=\"check\"\r\n" \
455 "\r\n" \
456 "option B\r\n" \
457 "--" kBoundary "\r\n" \
458 "Content-Disposition: form-data; name=\"txtarea\"\r\n" \
459 "\r\n" \
460 "Some text.\r\n" \
461 "Other.\r\n" \
462 "\r\n" \
463 "--" kBoundary "\r\n" \
464 "Content-Disposition: form-data; name=\"select\"\r\n" \
465 "\r\n" \
466 "one\r\n" \
467 "--" kBoundary "--"
468 // POST data input.
469 const char kMultipartBytes[] = kMultipartBytesBlock1 kMultipartBytesBlock2;
470 const char kMultipartBytesSplit1[] = kMultipartBytesBlock1;
471 const char kMultipartBytesSplit2[] = kMultipartBytesBlock2;
472 const char kUrlEncodedBytes[] = "text=test+text&file=test-file"
473 "&password=test+password&radio=Yes&check=option+A&check=option+B"
474 "&txtarea=Some+text.%0D%0AOther.%0D%0A&select=one";
475 const char kTextPlainBytes[] = "dummy text";
476 // POST data output.
477 const char kResultMultipart[] = "\"check\":[\"option A\",\"option B\"]," \
478 "\"file\":[\"test\"],\"password\":[\"test password\"]," \
479 "\"radio\":[\"Yes\"],\"select\":[\"one\"],\"text\":[\"test text\"]," \
480 "\"txtarea\":[\"Some text.\\r\\nOther.\\r\\n\"";
481 const char kResultUrlEncoded[] = "\"check\":[\"option+A\",\"option+B\"]," \
482 "\"file\":[\"test-file\"],\"password\":[\"test+password\"]," \
483 "\"radio\":[\"Yes\"],\"select\":[\"one\"],\"text\":[\"test+text\"]," \
484 "\"txtarea\":[\"Some+text.%0D%0AOther.%0D%0A\"";
485 const char* kResults[] =
486 {kResultMultipart, kResultMultipart, kResultUrlEncoded};
487 // Headers.
488 const char kUrlEncoded[] = "application/x-www-form-urlencoded";
489 const char kTextPlain[] = "text/plain";
490 const char kMultipart[] = "multipart/form-data; boundary=" kBoundary;
491 #undef kMultipartBytesBlock2
492 #undef kMultipartBytesBlock1
493 #undef kBoundary
494
495 // Set up a dummy extension name.
496 std::string extension_id("1");
497 ExtensionWebRequestEventRouter::RequestFilter filter;
498 int extra_info_spec =
499 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING |
500 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_POST_DATA;
501
502 // Subscribe to OnBeforeRequest.
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, 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, sizeof(kMultipartBytes)-1);
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 sizeof(kMultipartBytesSplit1)-1);
526 request2.AppendBytesToUpload(kMultipartBytesSplit2,
527 sizeof(kMultipartBytesSplit2)-1);
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, sizeof(kUrlEncodedBytes)-1);
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, sizeof(kTextPlainBytes)-1);
544 ipc_sender_.PushTask(base::Bind(&base::DoNothing));
545 request4.Start();
546
547 MessageLoop::current()->RunAllPending();
548
549 IPC::Message* message = NULL;
550 std::string post_data;
551 TestIPCSender::SentMessages::const_iterator i = ipc_sender_.sent_begin();
552 // The first 3 tests should succeed.
553 for (int test = 0; test < 3; ++test) {
554 EXPECT_FALSE(i == ipc_sender_.sent_end());
555 message = (i++)->get();
556 EXPECT_EQ(kPostDataFound, TestMessage(message, &post_data));
557 EXPECT_EQ(kResults[test], post_data);
558 }
559 // Whereas the last test should fail, text/plain is not supported for parsing.
560 EXPECT_FALSE(i == ipc_sender_.sent_end());
561 message = (i++)->get();
562 EXPECT_EQ(kNoPostData, TestMessage(message, &post_data));
563
564 EXPECT_TRUE(i == ipc_sender_.sent_end());
565
566 // Clean-up.
567 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
568 &profile_, extension_id, kEventName + "/1");
402 } 569 }
403 570
404 struct HeaderModificationTest_Header { 571 struct HeaderModificationTest_Header {
405 const char* name; 572 const char* name;
406 const char* value; 573 const char* value;
407 }; 574 };
408 575
409 struct HeaderModificationTest_Modification { 576 struct HeaderModificationTest_Modification {
410 enum Type { 577 enum Type {
411 SET, 578 SET,
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 true, 823 true,
657 ExtensionWebRequestEventRouter::ExtraInfoSpec::RESPONSE_HEADERS); 824 ExtensionWebRequestEventRouter::ExtraInfoSpec::RESPONSE_HEADERS);
658 TestInitFromValue( 825 TestInitFromValue(
659 "blocking", 826 "blocking",
660 true, 827 true,
661 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING); 828 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING);
662 TestInitFromValue( 829 TestInitFromValue(
663 "asyncBlocking", 830 "asyncBlocking",
664 true, 831 true,
665 ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING); 832 ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING);
833 TestInitFromValue(
834 "requestPostData",
835 true,
836 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_POST_DATA);
666 837
667 // Multiple valid values are bitwise-or'ed. 838 // Multiple valid values are bitwise-or'ed.
668 TestInitFromValue( 839 TestInitFromValue(
669 "requestHeaders,blocking", 840 "requestHeaders,blocking",
670 true, 841 true,
671 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS | 842 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS |
672 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING); 843 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING);
673 844
674 // Any invalid values lead to a bad parse. 845 // Any invalid values lead to a bad parse.
675 TestInitFromValue("invalidValue", false, 0); 846 TestInitFromValue("invalidValue", false, 0);
(...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after
1510 }; 1681 };
1511 for (size_t i = 0; i < arraysize(sensitive_urls); ++i) { 1682 for (size_t i = 0; i < arraysize(sensitive_urls); ++i) {
1512 EXPECT_TRUE(helpers::HideRequestForURL(GURL(sensitive_urls[i]))) 1683 EXPECT_TRUE(helpers::HideRequestForURL(GURL(sensitive_urls[i])))
1513 << sensitive_urls[i]; 1684 << sensitive_urls[i];
1514 } 1685 }
1515 for (size_t i = 0; i < arraysize(non_sensitive_urls); ++i) { 1686 for (size_t i = 0; i < arraysize(non_sensitive_urls); ++i) {
1516 EXPECT_FALSE(helpers::HideRequestForURL(GURL(non_sensitive_urls[i]))) 1687 EXPECT_FALSE(helpers::HideRequestForURL(GURL(non_sensitive_urls[i])))
1517 << non_sensitive_urls[i]; 1688 << non_sensitive_urls[i];
1518 } 1689 }
1519 } 1690 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698