| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "content/child/url_response_body_consumer.h" | 5 #include "content/child/url_response_body_consumer.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_forward.h" | 8 #include "base/callback_forward.h" |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "url/gurl.h" | 22 #include "url/gurl.h" |
| 23 #include "url/origin.h" | 23 #include "url/origin.h" |
| 24 | 24 |
| 25 namespace content { | 25 namespace content { |
| 26 | 26 |
| 27 namespace { | 27 namespace { |
| 28 | 28 |
| 29 class TestRequestPeer : public RequestPeer { | 29 class TestRequestPeer : public RequestPeer { |
| 30 public: | 30 public: |
| 31 struct Context; | 31 struct Context; |
| 32 explicit TestRequestPeer(Context* context) : context_(context) {} | 32 TestRequestPeer(Context* context, |
| 33 scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
| 34 : context_(context), task_runner_(std::move(task_runner)) {} |
| 33 | 35 |
| 34 void OnUploadProgress(uint64_t position, uint64_t size) override { | 36 void OnUploadProgress(uint64_t position, uint64_t size) override { |
| 35 ADD_FAILURE() << "OnUploadProgress should not be called."; | 37 ADD_FAILURE() << "OnUploadProgress should not be called."; |
| 36 } | 38 } |
| 37 | 39 |
| 38 bool OnReceivedRedirect(const net::RedirectInfo& redirect_info, | 40 bool OnReceivedRedirect(const net::RedirectInfo& redirect_info, |
| 39 const ResourceResponseInfo& info) override { | 41 const ResourceResponseInfo& info) override { |
| 40 ADD_FAILURE() << "OnReceivedRedirect should not be called."; | 42 ADD_FAILURE() << "OnReceivedRedirect should not be called."; |
| 41 return false; | 43 return false; |
| 42 } | 44 } |
| 43 | 45 |
| 44 void OnReceivedResponse(const ResourceResponseInfo& info) override { | 46 void OnReceivedResponse(const ResourceResponseInfo& info) override { |
| 45 ADD_FAILURE() << "OnReceivedResponse should not be called."; | 47 ADD_FAILURE() << "OnReceivedResponse should not be called."; |
| 46 } | 48 } |
| 47 | 49 |
| 48 void OnDownloadedData(int len, int encoded_data_length) override { | 50 void OnDownloadedData(int len, int encoded_data_length) override { |
| 49 ADD_FAILURE() << "OnDownloadedData should not be called."; | 51 ADD_FAILURE() << "OnDownloadedData should not be called."; |
| 50 } | 52 } |
| 51 | 53 |
| 52 void OnReceivedData(std::unique_ptr<ReceivedData> data) override { | 54 void OnReceivedData(std::unique_ptr<ReceivedData> data) override { |
| 53 EXPECT_FALSE(context_->complete); | 55 EXPECT_FALSE(context_->complete); |
| 54 context_->data.append(data->payload(), data->length()); | 56 context_->data.append(data->payload(), data->length()); |
| 57 if (context_->release_data_asynchronously) |
| 58 task_runner_->DeleteSoon(FROM_HERE, data.release()); |
| 55 context_->run_loop_quit_closure.Run(); | 59 context_->run_loop_quit_closure.Run(); |
| 56 } | 60 } |
| 57 | 61 |
| 58 void OnTransferSizeUpdated(int transfer_size_diff) override {} | 62 void OnTransferSizeUpdated(int transfer_size_diff) override {} |
| 59 | 63 |
| 60 void OnCompletedRequest(int error_code, | 64 void OnCompletedRequest(int error_code, |
| 61 bool was_ignored_by_handler, | 65 bool was_ignored_by_handler, |
| 62 bool stale_copy_in_cache, | 66 bool stale_copy_in_cache, |
| 63 const base::TimeTicks& completion_time, | 67 const base::TimeTicks& completion_time, |
| 64 int64_t total_transfer_size, | 68 int64_t total_transfer_size, |
| 65 int64_t encoded_body_size) override { | 69 int64_t encoded_body_size) override { |
| 66 EXPECT_FALSE(context_->complete); | 70 EXPECT_FALSE(context_->complete); |
| 67 context_->complete = true; | 71 context_->complete = true; |
| 68 context_->error_code = error_code; | 72 context_->error_code = error_code; |
| 69 context_->run_loop_quit_closure.Run(); | 73 context_->run_loop_quit_closure.Run(); |
| 70 } | 74 } |
| 71 | 75 |
| 72 struct Context { | 76 struct Context { |
| 73 // Data received. If downloading to file, remains empty. | 77 // Data received. If downloading to file, remains empty. |
| 74 std::string data; | 78 std::string data; |
| 75 bool complete = false; | 79 bool complete = false; |
| 76 base::Closure run_loop_quit_closure; | 80 base::Closure run_loop_quit_closure; |
| 77 int error_code = net::OK; | 81 int error_code = net::OK; |
| 82 bool release_data_asynchronously = false; |
| 78 }; | 83 }; |
| 79 | 84 |
| 80 private: | 85 private: |
| 81 Context* context_; | 86 Context* context_; |
| 87 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 82 | 88 |
| 83 DISALLOW_COPY_AND_ASSIGN(TestRequestPeer); | 89 DISALLOW_COPY_AND_ASSIGN(TestRequestPeer); |
| 84 }; | 90 }; |
| 85 | 91 |
| 86 class URLResponseBodyConsumerTest : public ::testing::Test, | 92 class URLResponseBodyConsumerTest : public ::testing::Test, |
| 87 public ::IPC::Sender { | 93 public ::IPC::Sender { |
| 88 protected: | 94 protected: |
| 89 URLResponseBodyConsumerTest() | 95 URLResponseBodyConsumerTest() |
| 90 : dispatcher_(new ResourceDispatcher(this, message_loop_.task_runner())) { | 96 : dispatcher_(new ResourceDispatcher(this, message_loop_.task_runner())) { |
| 91 } | 97 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 options.element_num_bytes = 1; | 129 options.element_num_bytes = 1; |
| 124 options.capacity_num_bytes = 1024; | 130 options.capacity_num_bytes = 1024; |
| 125 return options; | 131 return options; |
| 126 } | 132 } |
| 127 | 133 |
| 128 // Returns the request id. | 134 // Returns the request id. |
| 129 int SetUpRequestPeer(std::unique_ptr<ResourceRequest> request, | 135 int SetUpRequestPeer(std::unique_ptr<ResourceRequest> request, |
| 130 TestRequestPeer::Context* context) { | 136 TestRequestPeer::Context* context) { |
| 131 return dispatcher_->StartAsync( | 137 return dispatcher_->StartAsync( |
| 132 std::move(request), 0, nullptr, url::Origin(), | 138 std::move(request), 0, nullptr, url::Origin(), |
| 133 base::MakeUnique<TestRequestPeer>(context), | 139 base::MakeUnique<TestRequestPeer>(context, message_loop_.task_runner()), |
| 134 blink::WebURLRequest::LoadingIPCType::ChromeIPC, nullptr, nullptr); | 140 blink::WebURLRequest::LoadingIPCType::ChromeIPC, nullptr, nullptr); |
| 135 } | 141 } |
| 136 | 142 |
| 137 void Run(TestRequestPeer::Context* context) { | 143 void Run(TestRequestPeer::Context* context) { |
| 138 base::RunLoop run_loop; | 144 base::RunLoop run_loop; |
| 139 context->run_loop_quit_closure = run_loop.QuitClosure(); | 145 context->run_loop_quit_closure = run_loop.QuitClosure(); |
| 140 run_loop.Run(); | 146 run_loop.Run(); |
| 141 } | 147 } |
| 142 | 148 |
| 143 base::MessageLoop message_loop_; | 149 base::MessageLoop message_loop_; |
| 144 std::unique_ptr<ResourceDispatcher> dispatcher_; | 150 std::unique_ptr<ResourceDispatcher> dispatcher_; |
| 145 static const MojoWriteDataFlags kNone = MOJO_WRITE_DATA_FLAG_NONE; | 151 static const MojoWriteDataFlags kNone = MOJO_WRITE_DATA_FLAG_NONE; |
| 146 }; | 152 }; |
| 147 | 153 |
| 148 TEST_F(URLResponseBodyConsumerTest, ReceiveData) { | 154 TEST_F(URLResponseBodyConsumerTest, ReceiveData) { |
| 149 TestRequestPeer::Context context; | 155 TestRequestPeer::Context context; |
| 150 std::unique_ptr<ResourceRequest> request(CreateResourceRequest()); | 156 std::unique_ptr<ResourceRequest> request(CreateResourceRequest()); |
| 151 int request_id = SetUpRequestPeer(std::move(request), &context); | 157 int request_id = SetUpRequestPeer(std::move(request), &context); |
| 152 mojo::DataPipe data_pipe(CreateDataPipeOptions()); | 158 mojo::DataPipe data_pipe(CreateDataPipeOptions()); |
| 153 | 159 |
| 154 scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer( | 160 scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer( |
| 155 request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle), | 161 request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle), |
| 156 message_loop_.task_runner())); | 162 message_loop_.task_runner())); |
| 157 consumer->Start(message_loop_.task_runner().get()); | 163 consumer->Start(); |
| 158 | 164 |
| 159 mojo::ScopedDataPipeProducerHandle writer = | 165 mojo::ScopedDataPipeProducerHandle writer = |
| 160 std::move(data_pipe.producer_handle); | 166 std::move(data_pipe.producer_handle); |
| 161 std::string buffer = "hello"; | 167 std::string buffer = "hello"; |
| 162 uint32_t size = buffer.size(); | 168 uint32_t size = buffer.size(); |
| 163 MojoResult result = | 169 MojoResult result = |
| 164 mojo::WriteDataRaw(writer.get(), buffer.c_str(), &size, kNone); | 170 mojo::WriteDataRaw(writer.get(), buffer.c_str(), &size, kNone); |
| 165 ASSERT_EQ(MOJO_RESULT_OK, result); | 171 ASSERT_EQ(MOJO_RESULT_OK, result); |
| 166 ASSERT_EQ(buffer.size(), size); | 172 ASSERT_EQ(buffer.size(), size); |
| 167 | 173 |
| 168 Run(&context); | 174 Run(&context); |
| 169 | 175 |
| 170 EXPECT_FALSE(context.complete); | 176 EXPECT_FALSE(context.complete); |
| 171 EXPECT_EQ("hello", context.data); | 177 EXPECT_EQ("hello", context.data); |
| 172 } | 178 } |
| 173 | 179 |
| 174 TEST_F(URLResponseBodyConsumerTest, OnCompleteThenClose) { | 180 TEST_F(URLResponseBodyConsumerTest, OnCompleteThenClose) { |
| 175 TestRequestPeer::Context context; | 181 TestRequestPeer::Context context; |
| 176 std::unique_ptr<ResourceRequest> request(CreateResourceRequest()); | 182 std::unique_ptr<ResourceRequest> request(CreateResourceRequest()); |
| 177 int request_id = SetUpRequestPeer(std::move(request), &context); | 183 int request_id = SetUpRequestPeer(std::move(request), &context); |
| 178 mojo::DataPipe data_pipe(CreateDataPipeOptions()); | 184 mojo::DataPipe data_pipe(CreateDataPipeOptions()); |
| 179 | 185 |
| 180 scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer( | 186 scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer( |
| 181 request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle), | 187 request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle), |
| 182 message_loop_.task_runner())); | 188 message_loop_.task_runner())); |
| 183 consumer->Start(message_loop_.task_runner().get()); | 189 consumer->Start(); |
| 184 | 190 |
| 185 consumer->OnComplete(ResourceRequestCompletionStatus()); | 191 consumer->OnComplete(ResourceRequestCompletionStatus()); |
| 186 mojo::ScopedDataPipeProducerHandle writer = | 192 mojo::ScopedDataPipeProducerHandle writer = |
| 193 std::move(data_pipe.producer_handle); |
| 194 std::string buffer = "hello"; |
| 195 uint32_t size = buffer.size(); |
| 196 MojoResult result = |
| 197 mojo::WriteDataRaw(writer.get(), buffer.c_str(), &size, kNone); |
| 198 ASSERT_EQ(MOJO_RESULT_OK, result); |
| 199 ASSERT_EQ(buffer.size(), size); |
| 200 |
| 201 Run(&context); |
| 202 |
| 203 writer.reset(); |
| 204 EXPECT_FALSE(context.complete); |
| 205 EXPECT_EQ("hello", context.data); |
| 206 |
| 207 Run(&context); |
| 208 |
| 209 EXPECT_TRUE(context.complete); |
| 210 EXPECT_EQ("hello", context.data); |
| 211 } |
| 212 |
| 213 // Release the received data asynchronously. This leads to MOJO_RESULT_BUSY |
| 214 // from the BeginReadDataRaw call in OnReadable. |
| 215 TEST_F(URLResponseBodyConsumerTest, OnCompleteThenCloseWithAsyncRelease) { |
| 216 TestRequestPeer::Context context; |
| 217 context.release_data_asynchronously = true; |
| 218 std::unique_ptr<ResourceRequest> request(CreateResourceRequest()); |
| 219 int request_id = SetUpRequestPeer(std::move(request), &context); |
| 220 mojo::DataPipe data_pipe(CreateDataPipeOptions()); |
| 221 |
| 222 scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer( |
| 223 request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle), |
| 224 message_loop_.task_runner())); |
| 225 consumer->Start(); |
| 226 |
| 227 consumer->OnComplete(ResourceRequestCompletionStatus()); |
| 228 mojo::ScopedDataPipeProducerHandle writer = |
| 187 std::move(data_pipe.producer_handle); | 229 std::move(data_pipe.producer_handle); |
| 188 std::string buffer = "hello"; | 230 std::string buffer = "hello"; |
| 189 uint32_t size = buffer.size(); | 231 uint32_t size = buffer.size(); |
| 190 MojoResult result = | 232 MojoResult result = |
| 191 mojo::WriteDataRaw(writer.get(), buffer.c_str(), &size, kNone); | 233 mojo::WriteDataRaw(writer.get(), buffer.c_str(), &size, kNone); |
| 192 ASSERT_EQ(MOJO_RESULT_OK, result); | 234 ASSERT_EQ(MOJO_RESULT_OK, result); |
| 193 ASSERT_EQ(buffer.size(), size); | 235 ASSERT_EQ(buffer.size(), size); |
| 194 | 236 |
| 195 Run(&context); | 237 Run(&context); |
| 196 | 238 |
| 197 writer.reset(); | 239 writer.reset(); |
| 198 EXPECT_FALSE(context.complete); | 240 EXPECT_FALSE(context.complete); |
| 199 EXPECT_EQ("hello", context.data); | 241 EXPECT_EQ("hello", context.data); |
| 200 | 242 |
| 201 Run(&context); | 243 Run(&context); |
| 202 | 244 |
| 203 EXPECT_TRUE(context.complete); | 245 EXPECT_TRUE(context.complete); |
| 204 EXPECT_EQ("hello", context.data); | 246 EXPECT_EQ("hello", context.data); |
| 205 } | 247 } |
| 206 | 248 |
| 207 TEST_F(URLResponseBodyConsumerTest, CloseThenOnComplete) { | 249 TEST_F(URLResponseBodyConsumerTest, CloseThenOnComplete) { |
| 208 TestRequestPeer::Context context; | 250 TestRequestPeer::Context context; |
| 209 std::unique_ptr<ResourceRequest> request(CreateResourceRequest()); | 251 std::unique_ptr<ResourceRequest> request(CreateResourceRequest()); |
| 210 int request_id = SetUpRequestPeer(std::move(request), &context); | 252 int request_id = SetUpRequestPeer(std::move(request), &context); |
| 211 mojo::DataPipe data_pipe(CreateDataPipeOptions()); | 253 mojo::DataPipe data_pipe(CreateDataPipeOptions()); |
| 212 | 254 |
| 213 scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer( | 255 scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer( |
| 214 request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle), | 256 request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle), |
| 215 message_loop_.task_runner())); | 257 message_loop_.task_runner())); |
| 216 consumer->Start(message_loop_.task_runner().get()); | 258 consumer->Start(); |
| 217 | 259 |
| 218 ResourceRequestCompletionStatus status; | 260 ResourceRequestCompletionStatus status; |
| 219 status.error_code = net::ERR_FAILED; | 261 status.error_code = net::ERR_FAILED; |
| 220 data_pipe.producer_handle.reset(); | 262 data_pipe.producer_handle.reset(); |
| 221 consumer->OnComplete(status); | 263 consumer->OnComplete(status); |
| 222 | 264 |
| 223 Run(&context); | 265 Run(&context); |
| 224 | 266 |
| 225 EXPECT_TRUE(context.complete); | 267 EXPECT_TRUE(context.complete); |
| 226 EXPECT_EQ(net::ERR_FAILED, context.error_code); | 268 EXPECT_EQ(net::ERR_FAILED, context.error_code); |
| 227 EXPECT_EQ("", context.data); | 269 EXPECT_EQ("", context.data); |
| 228 } | 270 } |
| 229 | 271 |
| 230 } // namespace | 272 } // namespace |
| 231 | 273 |
| 232 } // namespace content | 274 } // namespace content |
| OLD | NEW |