| Index: content/child/url_response_body_consumer_unittest.cc
 | 
| diff --git a/content/child/url_response_body_consumer_unittest.cc b/content/child/url_response_body_consumer_unittest.cc
 | 
| index 8bf435ca338491fef7e5f626b31967b9b12dad27..3496b4e480af85b8965ab07ef77a285d3122a57c 100644
 | 
| --- a/content/child/url_response_body_consumer_unittest.cc
 | 
| +++ b/content/child/url_response_body_consumer_unittest.cc
 | 
| @@ -29,7 +29,9 @@ namespace {
 | 
|  class TestRequestPeer : public RequestPeer {
 | 
|   public:
 | 
|    struct Context;
 | 
| -  explicit TestRequestPeer(Context* context) : context_(context) {}
 | 
| +  TestRequestPeer(Context* context,
 | 
| +                  scoped_refptr<base::SingleThreadTaskRunner> task_runner)
 | 
| +      : context_(context), task_runner_(std::move(task_runner)) {}
 | 
|  
 | 
|    void OnUploadProgress(uint64_t position, uint64_t size) override {
 | 
|      ADD_FAILURE() << "OnUploadProgress should not be called.";
 | 
| @@ -52,6 +54,8 @@ class TestRequestPeer : public RequestPeer {
 | 
|    void OnReceivedData(std::unique_ptr<ReceivedData> data) override {
 | 
|      EXPECT_FALSE(context_->complete);
 | 
|      context_->data.append(data->payload(), data->length());
 | 
| +    if (context_->release_data_asynchronously)
 | 
| +      task_runner_->DeleteSoon(FROM_HERE, data.release());
 | 
|      context_->run_loop_quit_closure.Run();
 | 
|    }
 | 
|  
 | 
| @@ -75,10 +79,12 @@ class TestRequestPeer : public RequestPeer {
 | 
|      bool complete = false;
 | 
|      base::Closure run_loop_quit_closure;
 | 
|      int error_code = net::OK;
 | 
| +    bool release_data_asynchronously = false;
 | 
|    };
 | 
|  
 | 
|   private:
 | 
|    Context* context_;
 | 
| +  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 | 
|  
 | 
|    DISALLOW_COPY_AND_ASSIGN(TestRequestPeer);
 | 
|  };
 | 
| @@ -130,7 +136,7 @@ class URLResponseBodyConsumerTest : public ::testing::Test,
 | 
|                         TestRequestPeer::Context* context) {
 | 
|      return dispatcher_->StartAsync(
 | 
|          std::move(request), 0, nullptr, url::Origin(),
 | 
| -        base::MakeUnique<TestRequestPeer>(context),
 | 
| +        base::MakeUnique<TestRequestPeer>(context, message_loop_.task_runner()),
 | 
|          blink::WebURLRequest::LoadingIPCType::ChromeIPC, nullptr, nullptr);
 | 
|    }
 | 
|  
 | 
| @@ -154,7 +160,7 @@ TEST_F(URLResponseBodyConsumerTest, ReceiveData) {
 | 
|    scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer(
 | 
|        request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle),
 | 
|        message_loop_.task_runner()));
 | 
| -  consumer->Start(message_loop_.task_runner().get());
 | 
| +  consumer->Start();
 | 
|  
 | 
|    mojo::ScopedDataPipeProducerHandle writer =
 | 
|        std::move(data_pipe.producer_handle);
 | 
| @@ -180,7 +186,43 @@ TEST_F(URLResponseBodyConsumerTest, OnCompleteThenClose) {
 | 
|    scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer(
 | 
|        request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle),
 | 
|        message_loop_.task_runner()));
 | 
| -  consumer->Start(message_loop_.task_runner().get());
 | 
| +  consumer->Start();
 | 
| +
 | 
| +  consumer->OnComplete(ResourceRequestCompletionStatus());
 | 
| +  mojo::ScopedDataPipeProducerHandle writer =
 | 
| +      std::move(data_pipe.producer_handle);
 | 
| +  std::string buffer = "hello";
 | 
| +  uint32_t size = buffer.size();
 | 
| +  MojoResult result =
 | 
| +      mojo::WriteDataRaw(writer.get(), buffer.c_str(), &size, kNone);
 | 
| +  ASSERT_EQ(MOJO_RESULT_OK, result);
 | 
| +  ASSERT_EQ(buffer.size(), size);
 | 
| +
 | 
| +  Run(&context);
 | 
| +
 | 
| +  writer.reset();
 | 
| +  EXPECT_FALSE(context.complete);
 | 
| +  EXPECT_EQ("hello", context.data);
 | 
| +
 | 
| +  Run(&context);
 | 
| +
 | 
| +  EXPECT_TRUE(context.complete);
 | 
| +  EXPECT_EQ("hello", context.data);
 | 
| +}
 | 
| +
 | 
| +// Release the received data asynchronously. This leads to MOJO_RESULT_BUSY
 | 
| +// from the BeginReadDataRaw call in OnReadable.
 | 
| +TEST_F(URLResponseBodyConsumerTest, OnCompleteThenCloseWithAsyncRelease) {
 | 
| +  TestRequestPeer::Context context;
 | 
| +  context.release_data_asynchronously = true;
 | 
| +  std::unique_ptr<ResourceRequest> request(CreateResourceRequest());
 | 
| +  int request_id = SetUpRequestPeer(std::move(request), &context);
 | 
| +  mojo::DataPipe data_pipe(CreateDataPipeOptions());
 | 
| +
 | 
| +  scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer(
 | 
| +      request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle),
 | 
| +      message_loop_.task_runner()));
 | 
| +  consumer->Start();
 | 
|  
 | 
|    consumer->OnComplete(ResourceRequestCompletionStatus());
 | 
|    mojo::ScopedDataPipeProducerHandle writer =
 | 
| @@ -213,7 +255,7 @@ TEST_F(URLResponseBodyConsumerTest, CloseThenOnComplete) {
 | 
|    scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer(
 | 
|        request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle),
 | 
|        message_loop_.task_runner()));
 | 
| -  consumer->Start(message_loop_.task_runner().get());
 | 
| +  consumer->Start();
 | 
|  
 | 
|    ResourceRequestCompletionStatus status;
 | 
|    status.error_code = net::ERR_FAILED;
 | 
| 
 |