Chromium Code Reviews| Index: chrome/browser/extensions/api/web_request/web_request_api_unittest.cc |
| diff --git a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc |
| index fc3dc17c564494ba300ae51a06d757d2e47148ad..eea1b36b6e8cab2395b6fee787ba51d8c4a72c11 100644 |
| --- a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc |
| +++ b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc |
| @@ -31,6 +31,7 @@ |
| #include "net/base/capturing_net_log.h" |
| #include "net/base/mock_host_resolver.h" |
| #include "net/base/net_util.h" |
| +#include "net/base/upload_data.h" |
| #include "net/url_request/url_request_test_util.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| @@ -73,6 +74,32 @@ bool Contains(const Collection& collection, const Key& key) { |
| collection.end(); |
| } |
| +// Inspects the data attached to the |message| and tries to extract its |
| +// "postData" section into |post_data|. |
| +void GetPostData(IPC::Message* message, std::string* post_data, bool* success) { |
| + ASSERT_TRUE(success != NULL); |
| + *success = false; |
| + ASSERT_EQ(message->type(), ExtensionMsg_MessageInvoke::ID); |
| + ExtensionMsg_MessageInvoke::Param param; |
| + Value* temp_value = NULL; |
| + ASSERT_TRUE(ExtensionMsg_MessageInvoke::Read(message, ¶m)); |
| + ASSERT_GE(param.c.GetSize(), static_cast<size_t>(2)); |
| + ASSERT_TRUE(param.c.Get(1, &temp_value)); |
| + std::string args; |
| + ASSERT_TRUE(temp_value->GetAsString(&args)); |
| + const char kPostDataHead[] = "\"postData\":{"; |
| + size_t post_data_start = args.find(kPostDataHead); |
| + if (post_data_start == std::string::npos) |
| + return; |
| + post_data_start += strlen(kPostDataHead); |
| + const size_t post_data_end = args.find("}", post_data_start); |
| + ASSERT_NE(post_data_end, std::string::npos); |
| + const size_t post_data_length = (post_data_end - 1) - post_data_start; |
| + *post_data = std::string(args, post_data_start, post_data_length); |
| + *success = true; |
| + return; |
| +} |
| + |
| } // namespace |
| // A mock event router that responds to events with a pre-arranged queue of |
| @@ -398,7 +425,166 @@ TEST_F(ExtensionWebRequestTest, SimulateChancelWhileBlocked) { |
| ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( |
| &profile_, extension_id, kEventName + "/1"); |
| ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( |
| - &profile_, extension_id, kEventName2 + "/1"); |
| + &profile_, extension_id, kEventName2 + "/1"); |
| +} |
| + |
| +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.
|
| + // We verify that POST data are accessible to OnBeforeRequest listeners. |
| + // Construct the test data. |
| +#define kBoundary "THIS_IS_A_BOUNDARY" |
| +#define kMultipartBytesBlock1 "--" kBoundary "\r\n" \ |
| + "Content-Disposition: form-data; name=\"text\"\r\n" \ |
| + "\r\n" \ |
| + "test text\r\n" \ |
| + "--" kBoundary "\r\n" \ |
| + "Content-Disposition: form-data; name=\"file\"; filename=\"test\"\r\n" \ |
| + "Content-Type: application/octet-stream\r\n" \ |
| + "\r\n" |
| +#define kMultipartBytesBlock2 "\r\n" \ |
| + "--" kBoundary "\r\n" \ |
| + "Content-Disposition: form-data; name=\"password\"\r\n" \ |
| + "\r\n" \ |
| + "test password\r\n" \ |
| + "--" kBoundary "\r\n" \ |
| + "Content-Disposition: form-data; name=\"radio\"\r\n" \ |
| + "\r\n" \ |
| + "Yes\r\n" \ |
| + "--" kBoundary "\r\n" \ |
| + "Content-Disposition: form-data; name=\"check\"\r\n" \ |
| + "\r\n" \ |
| + "option A\r\n" \ |
| + "--" kBoundary "\r\n" \ |
| + "Content-Disposition: form-data; name=\"check\"\r\n" \ |
| + "\r\n" \ |
| + "option B\r\n" \ |
| + "--" kBoundary "\r\n" \ |
| + "Content-Disposition: form-data; name=\"txtarea\"\r\n" \ |
| + "\r\n" \ |
| + "Some text.\r\n" \ |
| + "Other.\r\n" \ |
| + "\r\n" \ |
| + "--" kBoundary "\r\n" \ |
| + "Content-Disposition: form-data; name=\"select\"\r\n" \ |
| + "\r\n" \ |
| + "one\r\n" \ |
| + "--" kBoundary "--" |
| + // POST data input. |
| + const char kMultipartBytes[] = kMultipartBytesBlock1 kMultipartBytesBlock2; |
| + const char kMultipartBytesSplit1[] = kMultipartBytesBlock1; |
| + const char kMultipartBytesSplit2[] = kMultipartBytesBlock2; |
| + const char kUrlEncodedBytes[] = "text=test+text&file=test" |
| + "&password=test+password&radio=Yes&check=option+A&check=option+B" |
| + "&txtarea=Some+text.%0D%0AOther.%0D%0A&select=one"; |
| + const char kTextPlainBytes[] = "dummy text"; |
| + // POST data output. |
| + const char kResultString[] = "\"check\":[\"option A\",\"option B\"]," \ |
| + "\"file\":[\"test\"],\"password\":[\"test password\"]," \ |
| + "\"radio\":[\"Yes\"],\"select\":[\"one\"],\"text\":[\"test text\"]," \ |
| + "\"txtarea\":[\"Some text.\\r\\nOther.\\r\\n\""; |
| + bool kResultExpected[] = {true, true, true, false, false}; |
| + // Headers. |
| + const char kUrlEncoded[] = "application/x-www-form-urlencoded"; |
| + const char kTextPlain[] = "text/plain"; |
| + const char kMultipart[] = "multipart/form-data; boundary=" kBoundary; |
| +#undef kMultipartBytesBlock2 |
| +#undef kMultipartBytesBlock1 |
| +#undef kBoundary |
| + |
| + // Set up a dummy extension name. |
| + ExtensionWebRequestEventRouter::RequestFilter filter; |
| + std::string extension_id("1"); |
| + int extra_info_spec_post = |
| + ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING | |
| + ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_POST_DATA; |
| + int extra_info_spec_no_post = |
| + ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING; |
| + |
| + // Subscribe to OnBeforeRequest with POST data requirement. |
| + const std::string kEventName(keys::kOnBeforeRequest); |
| + base::WeakPtrFactory<TestIPCSender> ipc_sender_factory(&ipc_sender_); |
| + ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( |
| + &profile_, extension_id, extension_id, kEventName, kEventName + "/1", |
| + filter, extra_info_spec_post, ipc_sender_factory.GetWeakPtr()); |
| + |
| + // The request URL can be arbitrary but must have a HTTP or HTTPS scheme. |
| + GURL request_url("http://www.example.com"); |
| + |
| + // First test: multipart POST data in one lump. |
| + net::URLRequest request1(request_url, &delegate_, context_.get()); |
| + request1.set_method("POST"); |
| + request1.SetExtraRequestHeaderByName("Content-Type", kMultipart, true); |
| + request1.AppendBytesToUpload(kMultipartBytes, strlen(kMultipartBytes)); |
| + ipc_sender_.PushTask(base::Bind(&base::DoNothing)); |
| + request1.Start(); |
| + |
| + // Second test: multipart POST data in several lumps. |
| + net::URLRequest request2(request_url, &delegate_, context_.get()); |
| + request2.set_method("POST"); |
| + request2.SetExtraRequestHeaderByName("Content-Type", kMultipart, true); |
| + request2.AppendBytesToUpload(kMultipartBytesSplit1, |
| + strlen(kMultipartBytesSplit1)); |
| + request2.AppendBytesToUpload(kMultipartBytesSplit2, |
| + strlen(kMultipartBytesSplit2)); |
| + ipc_sender_.PushTask(base::Bind(&base::DoNothing)); |
| + request2.Start(); |
| + |
| + // Third test: URL-encoded POST data. |
| + net::URLRequest request3(request_url, &delegate_, context_.get()); |
| + request3.set_method("POST"); |
| + request3.SetExtraRequestHeaderByName("Content-Type", kUrlEncoded, true); |
| + request3.AppendBytesToUpload(kUrlEncodedBytes, strlen(kUrlEncodedBytes)); |
| + ipc_sender_.PushTask(base::Bind(&base::DoNothing)); |
| + request3.Start(); |
| + |
| + // Fourth test: text/plain POST data in one lump. |
| + net::URLRequest request4(request_url, &delegate_, context_.get()); |
| + request4.set_method("POST"); |
| + request4.SetExtraRequestHeaderByName("Content-Type", kTextPlain, true); |
| + request4.AppendBytesToUpload(kTextPlainBytes, strlen(kTextPlainBytes)); |
| + ipc_sender_.PushTask(base::Bind(&base::DoNothing)); |
| + request4.Start(); |
| + |
| + MessageLoop::current()->RunAllPending(); |
| + |
| + // Now remove the requirement of POST data. |
| + ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( |
| + &profile_, extension_id, kEventName + "/1"); |
| + ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( |
| + &profile_, extension_id, extension_id, kEventName, kEventName + "/1", |
| + filter, extra_info_spec_no_post, ipc_sender_factory.GetWeakPtr()); |
| + |
| + // Fifth test is the same as the first. Nobody asked for POST data, |
| + // so in this case, none should be reported. |
| + net::URLRequest request5(request_url, &delegate_, context_.get()); |
| + request5.set_method("POST"); |
| + request5.SetExtraRequestHeaderByName("Content-Type", kMultipart, true); |
| + request5.AppendBytesToUpload(kMultipartBytes, strlen(kMultipartBytes)); |
| + ipc_sender_.PushTask(base::Bind(&base::DoNothing)); |
| + request5.Start(); |
| + |
| + MessageLoop::current()->RunAllPending(); |
| + |
| + IPC::Message* message = NULL; |
| + std::string post_data; |
| + TestIPCSender::SentMessages::const_iterator i = ipc_sender_.sent_begin(); |
| + for (size_t test = 0; test < arraysize(kResultExpected); ++test) { |
| + EXPECT_NE(i, ipc_sender_.sent_end()); |
| + message = (i++)->get(); |
| + bool post_data_found; |
| + GetPostData(message, &post_data, &post_data_found); |
| + if (kResultExpected[test]) { |
| + EXPECT_TRUE(post_data_found); |
| + EXPECT_EQ(kResultString, post_data); |
| + } else { |
| + EXPECT_FALSE(post_data_found); |
| + } |
| + } |
| + |
| + EXPECT_TRUE(i == ipc_sender_.sent_end()); |
| + |
| + // Clean-up. |
| + ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( |
| + &profile_, extension_id, kEventName + "/1"); |
| } |
| struct HeaderModificationTest_Header { |
| @@ -663,6 +849,10 @@ TEST_F(ExtensionWebRequestTest, InitFromValue) { |
| "asyncBlocking", |
| true, |
| ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING); |
| + TestInitFromValue( |
| + "requestPostData", |
| + true, |
| + ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_POST_DATA); |
| // Multiple valid values are bitwise-or'ed. |
| TestInitFromValue( |