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

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: Deleting a forgotten comment 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 {
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, &param)) 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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698