Index: content/child/resource_dispatcher_unittest.cc |
diff --git a/content/child/resource_dispatcher_unittest.cc b/content/child/resource_dispatcher_unittest.cc |
index a2e457edfc159b77211a719662e9c2e40176a779..c7bedc43c84ff08d59cf7a36d70aedbc757b2813 100644 |
--- a/content/child/resource_dispatcher_unittest.cc |
+++ b/content/child/resource_dispatcher_unittest.cc |
@@ -93,6 +93,11 @@ class TestRequestPeer : public RequestPeer { |
EXPECT_FALSE(context_->complete); |
context_->data.append(data->payload(), data->length()); |
context_->total_encoded_data_length += data->encoded_data_length(); |
+ |
+ if (context_->cancel_on_receive_data) { |
+ dispatcher_->Cancel(context_->request_id); |
+ context_->cancelled = true; |
+ } |
} |
void OnCompletedRequest(int error_code, |
@@ -117,6 +122,7 @@ class TestRequestPeer : public RequestPeer { |
int seen_redirects = 0; |
bool cancel_on_receive_response = false; |
+ bool cancel_on_receive_data = false; |
bool received_response = false; |
// Data received. If downloading to file, remains empty. |
@@ -810,6 +816,113 @@ TEST_F(ResourceDispatcherTest, CancelDeferredRequest) { |
EXPECT_EQ(0, peer_context.seen_redirects); |
} |
+// Checks cancelling a request while flushing deferred requests from |
+// the FlushDeferredMessages() task. |
+TEST_F(ResourceDispatcherTest, CancelWhileFlushingDeferredRequests) { |
+ std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false)); |
+ TestRequestPeer::Context peer_context; |
+ int request_id = StartAsync(std::move(request), NULL, &peer_context); |
+ |
+ // Cancel the request when the data message is handled. |
+ peer_context.cancel_on_receive_data = true; |
+ |
+ int id = ConsumeRequestResource(); |
+ EXPECT_EQ(0u, queued_messages()); |
+ |
+ dispatcher()->SetDefersLoading(request_id, true); |
+ NotifyReceivedResponse(id); |
+ NotifySetDataBuffer(id, strlen(kTestPageContents)); |
+ NotifyDataReceived(id, kTestPageContents); |
+ |
+ // None of the messages should have been processed yet. |
+ EXPECT_EQ("", peer_context.data); |
+ EXPECT_FALSE(peer_context.complete); |
+ EXPECT_EQ(0u, queued_messages()); |
+ |
+ dispatcher()->SetDefersLoading(request_id, false); |
+ |
+ // Make sure that the FlushDeferredMessages() task posted from |
+ // SetDefersLoading() is run. It should dispatch all the deferred |
+ // messages. |
+ base::RunLoop().RunUntilIdle(); |
+ |
+ // When the deferred DataReceived is dispatched, the handler will |
+ // cancel the request, but the ACK is sent after the handler |
+ // returns, so the cancel request ends up before the ACK in the |
+ // message queue. |
+ ConsumeCancelRequest(id); |
+ ConsumeDataReceived_ACK(id); |
+ |
+ // The data was consumed before the handler canceled |
+ // the request, so the data should have been received. |
+ EXPECT_EQ(kTestPageContents, peer_context.data); |
+ EXPECT_FALSE(peer_context.complete); |
+ EXPECT_EQ(0u, queued_messages()); |
+} |
+ |
+// Checks cancelling a request while flushing deferred requests from |
+// OnMessageReceived(). |
+TEST_F(ResourceDispatcherTest, |
+ CancelWhileFlushingDeferredRequestsFromOnMessageReceived) { |
+ std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false)); |
+ TestRequestPeer::Context peer_context; |
+ int request_id = StartAsync(std::move(request), NULL, &peer_context); |
+ |
+ // Cancel the request when the data message is handled. |
+ peer_context.cancel_on_receive_data = true; |
+ |
+ int id = ConsumeRequestResource(); |
+ EXPECT_EQ(0u, queued_messages()); |
+ |
+ dispatcher()->SetDefersLoading(request_id, true); |
+ NotifyReceivedResponse(id); |
+ NotifySetDataBuffer(id, strlen(kTestPageContents)); |
+ NotifyDataReceived(id, kTestPageContents); |
+ |
+ // None of the messages should have been processed yet. |
+ EXPECT_EQ("", peer_context.data); |
+ EXPECT_FALSE(peer_context.complete); |
+ EXPECT_EQ(0u, queued_messages()); |
+ |
+ dispatcher()->SetDefersLoading(request_id, false); |
+ |
+ // SetDefersLoading() posts a task to run FlushDeferredMessages() to dispatch |
+ // the deferred messages. Since the message loop hasn't been run yet the |
+ // task hasn't been run either and no IPC-messages should have been |
+ // dispatched. |
+ EXPECT_EQ("", peer_context.data); |
+ EXPECT_FALSE(peer_context.complete); |
+ EXPECT_EQ(0u, queued_messages()); |
+ |
+ // Calling NotifyRequestComplete() here, before the task from |
+ // SetDefersLoading() has been run, triggers the flush in |
+ // OnMessageReceived(). |
+ NotifyRequestComplete(id, strlen(kTestPageContents)); |
+ |
+ // When the deferred DataReceived is dispatched, the handler will |
+ // cancel the request, but the ACK is sent after the handler |
+ // returns, so the cancel request ends up before the ACK in the |
+ // message queue. |
+ ConsumeCancelRequest(id); |
+ ConsumeDataReceived_ACK(id); |
+ |
+ // The data was consumed before the handler canceled |
+ // the request, so the data should have been received. |
+ EXPECT_EQ(kTestPageContents, peer_context.data); |
+ EXPECT_FALSE(peer_context.complete); |
+ EXPECT_EQ(0u, queued_messages()); |
+ |
+ // Make sure that the FlushDeferredMessages() task posted from |
+ // SetDefersLoading() is run. The messages should already have been |
+ // flushed above, so it should be a NOOP. |
+ base::RunLoop().RunUntilIdle(); |
+ |
+ // Check that the task didn't change anything. |
+ EXPECT_EQ(kTestPageContents, peer_context.data); |
+ EXPECT_FALSE(peer_context.complete); |
+ EXPECT_EQ(0u, queued_messages()); |
+} |
+ |
TEST_F(ResourceDispatcherTest, DownloadToFile) { |
std::unique_ptr<ResourceRequest> request(CreateResourceRequest(true)); |
TestRequestPeer::Context peer_context; |