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/browser/loader/mojo_async_resource_handler.h" | 5 #include "content/browser/loader/mojo_async_resource_handler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 } else { | 136 } else { |
137 GetRequestInfo()->set_on_transfer(base::Bind(&NotReached)); | 137 GetRequestInfo()->set_on_transfer(base::Bind(&NotReached)); |
138 } | 138 } |
139 } | 139 } |
140 | 140 |
141 MojoAsyncResourceHandler::~MojoAsyncResourceHandler() { | 141 MojoAsyncResourceHandler::~MojoAsyncResourceHandler() { |
142 if (has_checked_for_sufficient_resources_) | 142 if (has_checked_for_sufficient_resources_) |
143 rdh_->FinishedWithResourcesForRequest(request()); | 143 rdh_->FinishedWithResourcesForRequest(request()); |
144 } | 144 } |
145 | 145 |
146 bool MojoAsyncResourceHandler::OnRequestRedirected( | 146 void MojoAsyncResourceHandler::OnRequestRedirected( |
147 const net::RedirectInfo& redirect_info, | 147 const net::RedirectInfo& redirect_info, |
148 ResourceResponse* response, | 148 ResourceResponse* response, |
149 bool* defer) { | 149 std::unique_ptr<ResourceController> controller) { |
150 // Unlike OnResponseStarted, OnRequestRedirected will NOT be preceded by | 150 // Unlike OnResponseStarted, OnRequestRedirected will NOT be preceded by |
151 // OnWillRead. | 151 // OnWillRead. |
| 152 DCHECK(!has_controller()); |
152 DCHECK(!shared_writer_); | 153 DCHECK(!shared_writer_); |
153 | 154 |
154 *defer = true; | |
155 request()->LogBlockedBy("MojoAsyncResourceHandler"); | 155 request()->LogBlockedBy("MojoAsyncResourceHandler"); |
| 156 HoldController(std::move(controller)); |
156 did_defer_on_redirect_ = true; | 157 did_defer_on_redirect_ = true; |
157 | 158 |
158 NetLogObserver::PopulateResponseInfo(request(), response); | 159 NetLogObserver::PopulateResponseInfo(request(), response); |
159 response->head.encoded_data_length = request()->GetTotalReceivedBytes(); | 160 response->head.encoded_data_length = request()->GetTotalReceivedBytes(); |
160 response->head.request_start = request()->creation_time(); | 161 response->head.request_start = request()->creation_time(); |
161 response->head.response_start = base::TimeTicks::Now(); | 162 response->head.response_start = base::TimeTicks::Now(); |
162 // TODO(davidben): Is it necessary to pass the new first party URL for | 163 // TODO(davidben): Is it necessary to pass the new first party URL for |
163 // cookies? The only case where it can change is top-level navigation requests | 164 // cookies? The only case where it can change is top-level navigation requests |
164 // and hopefully those will eventually all be owned by the browser. It's | 165 // and hopefully those will eventually all be owned by the browser. It's |
165 // possible this is still needed while renderer-owned ones exist. | 166 // possible this is still needed while renderer-owned ones exist. |
166 url_loader_client_->OnReceiveRedirect(redirect_info, response->head); | 167 url_loader_client_->OnReceiveRedirect(redirect_info, response->head); |
167 return true; | |
168 } | 168 } |
169 | 169 |
170 bool MojoAsyncResourceHandler::OnResponseStarted(ResourceResponse* response, | 170 void MojoAsyncResourceHandler::OnResponseStarted( |
171 bool* defer) { | 171 ResourceResponse* response, |
| 172 std::unique_ptr<ResourceController> controller) { |
| 173 DCHECK(!has_controller()); |
| 174 |
172 if (upload_progress_tracker_) { | 175 if (upload_progress_tracker_) { |
173 upload_progress_tracker_->OnUploadCompleted(); | 176 upload_progress_tracker_->OnUploadCompleted(); |
174 upload_progress_tracker_ = nullptr; | 177 upload_progress_tracker_ = nullptr; |
175 } | 178 } |
176 | 179 |
177 const ResourceRequestInfoImpl* info = GetRequestInfo(); | 180 const ResourceRequestInfoImpl* info = GetRequestInfo(); |
178 if (rdh_->delegate()) { | 181 if (rdh_->delegate()) { |
179 rdh_->delegate()->OnResponseStarted(request(), info->GetContext(), | 182 rdh_->delegate()->OnResponseStarted(request(), info->GetContext(), |
180 response); | 183 response); |
181 } | 184 } |
(...skipping 17 matching lines...) Expand all Loading... |
199 url_loader_client_->OnReceiveResponse(response->head, | 202 url_loader_client_->OnReceiveResponse(response->head, |
200 std::move(downloaded_file_ptr)); | 203 std::move(downloaded_file_ptr)); |
201 | 204 |
202 net::IOBufferWithSize* metadata = GetResponseMetadata(request()); | 205 net::IOBufferWithSize* metadata = GetResponseMetadata(request()); |
203 if (metadata) { | 206 if (metadata) { |
204 const uint8_t* data = reinterpret_cast<const uint8_t*>(metadata->data()); | 207 const uint8_t* data = reinterpret_cast<const uint8_t*>(metadata->data()); |
205 | 208 |
206 url_loader_client_->OnReceiveCachedMetadata( | 209 url_loader_client_->OnReceiveCachedMetadata( |
207 std::vector<uint8_t>(data, data + metadata->size())); | 210 std::vector<uint8_t>(data, data + metadata->size())); |
208 } | 211 } |
209 return true; | 212 |
| 213 controller->Resume(); |
210 } | 214 } |
211 | 215 |
212 bool MojoAsyncResourceHandler::OnWillStart(const GURL& url, bool* defer) { | 216 void MojoAsyncResourceHandler::OnWillStart( |
| 217 const GURL& url, |
| 218 std::unique_ptr<ResourceController> controller) { |
213 if (GetRequestInfo()->is_upload_progress_enabled() && | 219 if (GetRequestInfo()->is_upload_progress_enabled() && |
214 request()->has_upload()) { | 220 request()->has_upload()) { |
215 upload_progress_tracker_ = CreateUploadProgressTracker( | 221 upload_progress_tracker_ = CreateUploadProgressTracker( |
216 FROM_HERE, | 222 FROM_HERE, |
217 base::BindRepeating(&MojoAsyncResourceHandler::SendUploadProgress, | 223 base::BindRepeating(&MojoAsyncResourceHandler::SendUploadProgress, |
218 base::Unretained(this))); | 224 base::Unretained(this))); |
219 } | 225 } |
220 | 226 |
221 return true; | 227 controller->Resume(); |
222 } | 228 } |
223 | 229 |
224 bool MojoAsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, | 230 bool MojoAsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, |
225 int* buf_size, | 231 int* buf_size, |
226 int min_size) { | 232 int min_size) { |
227 DCHECK_EQ(-1, min_size); | 233 DCHECK_EQ(-1, min_size); |
228 | 234 |
| 235 // TODO(mmenke): Cancel with net::ERR_INSUFFICIENT_RESOURCES instead. |
229 if (!CheckForSufficientResource()) | 236 if (!CheckForSufficientResource()) |
230 return false; | 237 return false; |
231 | 238 |
232 if (!shared_writer_) { | 239 if (!shared_writer_) { |
233 MojoCreateDataPipeOptions options; | 240 MojoCreateDataPipeOptions options; |
234 options.struct_size = sizeof(MojoCreateDataPipeOptions); | 241 options.struct_size = sizeof(MojoCreateDataPipeOptions); |
235 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; | 242 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; |
236 options.element_num_bytes = 1; | 243 options.element_num_bytes = 1; |
237 options.capacity_num_bytes = g_allocation_size; | 244 options.capacity_num_bytes = g_allocation_size; |
238 mojo::DataPipe data_pipe(options); | 245 mojo::DataPipe data_pipe(options); |
(...skipping 26 matching lines...) Expand all Loading... |
265 is_using_io_buffer_not_from_writer_ = true; | 272 is_using_io_buffer_not_from_writer_ = true; |
266 buffer_ = new net::IOBufferWithSize(kMinAllocationSize); | 273 buffer_ = new net::IOBufferWithSize(kMinAllocationSize); |
267 } | 274 } |
268 | 275 |
269 DCHECK_EQ(0u, buffer_offset_); | 276 DCHECK_EQ(0u, buffer_offset_); |
270 *buf = buffer_; | 277 *buf = buffer_; |
271 *buf_size = buffer_->size(); | 278 *buf_size = buffer_->size(); |
272 return true; | 279 return true; |
273 } | 280 } |
274 | 281 |
275 bool MojoAsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { | 282 void MojoAsyncResourceHandler::OnReadCompleted( |
| 283 int bytes_read, |
| 284 std::unique_ptr<ResourceController> controller) { |
| 285 DCHECK(!has_controller()); |
276 DCHECK_GE(bytes_read, 0); | 286 DCHECK_GE(bytes_read, 0); |
277 DCHECK(buffer_); | 287 DCHECK(buffer_); |
278 | 288 |
279 if (!bytes_read) | 289 if (!bytes_read) { |
280 return true; | 290 controller->Resume(); |
| 291 return; |
| 292 } |
281 | 293 |
282 const ResourceRequestInfoImpl* info = GetRequestInfo(); | 294 const ResourceRequestInfoImpl* info = GetRequestInfo(); |
283 if (info->ShouldReportRawHeaders()) { | 295 if (info->ShouldReportRawHeaders()) { |
284 auto transfer_size_diff = CalculateRecentlyReceivedBytes(); | 296 auto transfer_size_diff = CalculateRecentlyReceivedBytes(); |
285 if (transfer_size_diff > 0) | 297 if (transfer_size_diff > 0) |
286 url_loader_client_->OnTransferSizeUpdated(transfer_size_diff); | 298 url_loader_client_->OnTransferSizeUpdated(transfer_size_diff); |
287 } | 299 } |
288 | 300 |
289 if (response_body_consumer_handle_.is_valid()) { | 301 if (response_body_consumer_handle_.is_valid()) { |
290 // Send the data pipe on the first OnReadCompleted call. | 302 // Send the data pipe on the first OnReadCompleted call. |
291 url_loader_client_->OnStartLoadingResponseBody( | 303 url_loader_client_->OnStartLoadingResponseBody( |
292 std::move(response_body_consumer_handle_)); | 304 std::move(response_body_consumer_handle_)); |
293 response_body_consumer_handle_.reset(); | 305 response_body_consumer_handle_.reset(); |
294 } | 306 } |
295 | 307 |
296 if (is_using_io_buffer_not_from_writer_) { | 308 if (is_using_io_buffer_not_from_writer_) { |
297 // Couldn't allocate a buffer on the data pipe in OnWillRead. | 309 // Couldn't allocate a buffer on the data pipe in OnWillRead. |
298 DCHECK_EQ(0u, buffer_bytes_read_); | 310 DCHECK_EQ(0u, buffer_bytes_read_); |
299 buffer_bytes_read_ = bytes_read; | 311 buffer_bytes_read_ = bytes_read; |
300 if (!CopyReadDataToDataPipe(defer)) | 312 bool defer = false; |
301 return false; | 313 if (!CopyReadDataToDataPipe(&defer)) { |
302 if (*defer) { | 314 controller->Cancel(); |
| 315 return; |
| 316 } |
| 317 if (defer) { |
303 request()->LogBlockedBy("MojoAsyncResourceHandler"); | 318 request()->LogBlockedBy("MojoAsyncResourceHandler"); |
304 did_defer_on_writing_ = true; | 319 did_defer_on_writing_ = true; |
| 320 HoldController(std::move(controller)); |
| 321 return; |
305 } | 322 } |
306 return true; | 323 controller->Resume(); |
| 324 return; |
307 } | 325 } |
308 | 326 |
309 if (EndWrite(bytes_read) != MOJO_RESULT_OK) | 327 if (EndWrite(bytes_read) != MOJO_RESULT_OK) { |
310 return false; | 328 controller->Cancel(); |
| 329 return; |
| 330 } |
311 // Allocate a buffer for the next OnWillRead call here, because OnWillRead | 331 // Allocate a buffer for the next OnWillRead call here, because OnWillRead |
312 // doesn't have |defer| parameter. | 332 // doesn't have |defer| parameter. |
313 if (!AllocateWriterIOBuffer(&buffer_, defer)) | 333 bool defer = false; |
314 return false; | 334 if (!AllocateWriterIOBuffer(&buffer_, &defer)) { |
315 if (*defer) { | 335 controller->Cancel(); |
| 336 return; |
| 337 } |
| 338 if (defer) { |
316 request()->LogBlockedBy("MojoAsyncResourceHandler"); | 339 request()->LogBlockedBy("MojoAsyncResourceHandler"); |
317 did_defer_on_writing_ = true; | 340 did_defer_on_writing_ = true; |
| 341 HoldController(std::move(controller)); |
| 342 return; |
318 } | 343 } |
319 return true; | 344 |
| 345 controller->Resume(); |
320 } | 346 } |
321 | 347 |
322 void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) { | 348 void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) { |
323 url_loader_client_->OnDataDownloaded(bytes_downloaded, | 349 url_loader_client_->OnDataDownloaded(bytes_downloaded, |
324 CalculateRecentlyReceivedBytes()); | 350 CalculateRecentlyReceivedBytes()); |
325 } | 351 } |
326 | 352 |
327 void MojoAsyncResourceHandler::FollowRedirect() { | 353 void MojoAsyncResourceHandler::FollowRedirect() { |
328 if (!request()->status().is_success()) { | 354 if (!request()->status().is_success()) { |
329 DVLOG(1) << "FollowRedirect for invalid request"; | 355 DVLOG(1) << "FollowRedirect for invalid request"; |
330 return; | 356 return; |
331 } | 357 } |
332 if (!did_defer_on_redirect_) { | 358 if (!did_defer_on_redirect_) { |
333 DVLOG(1) << "Malformed FollowRedirect request"; | 359 DVLOG(1) << "Malformed FollowRedirect request"; |
334 ReportBadMessage("Malformed FollowRedirect request"); | 360 ReportBadMessage("Malformed FollowRedirect request"); |
335 return; | 361 return; |
336 } | 362 } |
337 | 363 |
338 DCHECK(!did_defer_on_writing_); | 364 DCHECK(!did_defer_on_writing_); |
339 did_defer_on_redirect_ = false; | 365 did_defer_on_redirect_ = false; |
340 request()->LogUnblocked(); | 366 request()->LogUnblocked(); |
341 controller()->Resume(); | 367 Resume(); |
342 } | 368 } |
343 | 369 |
344 void MojoAsyncResourceHandler::OnWritableForTesting() { | 370 void MojoAsyncResourceHandler::OnWritableForTesting() { |
345 OnWritable(MOJO_RESULT_OK); | 371 OnWritable(MOJO_RESULT_OK); |
346 } | 372 } |
347 | 373 |
348 void MojoAsyncResourceHandler::SetAllocationSizeForTesting(size_t size) { | 374 void MojoAsyncResourceHandler::SetAllocationSizeForTesting(size_t size) { |
349 g_allocation_size = size; | 375 g_allocation_size = size; |
350 } | 376 } |
351 | 377 |
(...skipping 10 matching lines...) Expand all Loading... |
362 return mojo::EndWriteDataRaw(shared_writer_->writer(), written); | 388 return mojo::EndWriteDataRaw(shared_writer_->writer(), written); |
363 } | 389 } |
364 | 390 |
365 net::IOBufferWithSize* MojoAsyncResourceHandler::GetResponseMetadata( | 391 net::IOBufferWithSize* MojoAsyncResourceHandler::GetResponseMetadata( |
366 net::URLRequest* request) { | 392 net::URLRequest* request) { |
367 return request->response_info().metadata.get(); | 393 return request->response_info().metadata.get(); |
368 } | 394 } |
369 | 395 |
370 void MojoAsyncResourceHandler::OnResponseCompleted( | 396 void MojoAsyncResourceHandler::OnResponseCompleted( |
371 const net::URLRequestStatus& status, | 397 const net::URLRequestStatus& status, |
372 bool* defer) { | 398 std::unique_ptr<ResourceController> controller) { |
373 // Ensure sending the final upload progress message here, since | 399 // Ensure sending the final upload progress message here, since |
374 // OnResponseCompleted can be called without OnResponseStarted on cancellation | 400 // OnResponseCompleted can be called without OnResponseStarted on cancellation |
375 // or error cases. | 401 // or error cases. |
376 if (upload_progress_tracker_) { | 402 if (upload_progress_tracker_) { |
377 upload_progress_tracker_->OnUploadCompleted(); | 403 upload_progress_tracker_->OnUploadCompleted(); |
378 upload_progress_tracker_ = nullptr; | 404 upload_progress_tracker_ = nullptr; |
379 } | 405 } |
380 | 406 |
381 shared_writer_ = nullptr; | 407 shared_writer_ = nullptr; |
382 buffer_ = nullptr; | 408 buffer_ = nullptr; |
(...skipping 21 matching lines...) Expand all Loading... |
404 ResourceRequestCompletionStatus request_complete_data; | 430 ResourceRequestCompletionStatus request_complete_data; |
405 request_complete_data.error_code = error_code; | 431 request_complete_data.error_code = error_code; |
406 request_complete_data.was_ignored_by_handler = was_ignored_by_handler; | 432 request_complete_data.was_ignored_by_handler = was_ignored_by_handler; |
407 request_complete_data.exists_in_cache = request()->response_info().was_cached; | 433 request_complete_data.exists_in_cache = request()->response_info().was_cached; |
408 request_complete_data.completion_time = base::TimeTicks::Now(); | 434 request_complete_data.completion_time = base::TimeTicks::Now(); |
409 request_complete_data.encoded_data_length = | 435 request_complete_data.encoded_data_length = |
410 request()->GetTotalReceivedBytes(); | 436 request()->GetTotalReceivedBytes(); |
411 request_complete_data.encoded_body_length = request()->GetRawBodyBytes(); | 437 request_complete_data.encoded_body_length = request()->GetRawBodyBytes(); |
412 | 438 |
413 url_loader_client_->OnComplete(request_complete_data); | 439 url_loader_client_->OnComplete(request_complete_data); |
| 440 controller->Resume(); |
414 } | 441 } |
415 | 442 |
416 bool MojoAsyncResourceHandler::CopyReadDataToDataPipe(bool* defer) { | 443 bool MojoAsyncResourceHandler::CopyReadDataToDataPipe(bool* defer) { |
417 while (true) { | 444 while (true) { |
418 scoped_refptr<net::IOBufferWithSize> dest; | 445 scoped_refptr<net::IOBufferWithSize> dest; |
419 if (!AllocateWriterIOBuffer(&dest, defer)) | 446 if (!AllocateWriterIOBuffer(&dest, defer)) |
420 return false; | 447 return false; |
421 if (*defer) | 448 if (*defer) |
422 return true; | 449 return true; |
423 if (buffer_bytes_read_ == 0) { | 450 if (buffer_bytes_read_ == 0) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 } | 486 } |
460 | 487 |
461 bool MojoAsyncResourceHandler::CheckForSufficientResource() { | 488 bool MojoAsyncResourceHandler::CheckForSufficientResource() { |
462 if (has_checked_for_sufficient_resources_) | 489 if (has_checked_for_sufficient_resources_) |
463 return true; | 490 return true; |
464 has_checked_for_sufficient_resources_ = true; | 491 has_checked_for_sufficient_resources_ = true; |
465 | 492 |
466 if (rdh_->HasSufficientResourcesForRequest(request())) | 493 if (rdh_->HasSufficientResourcesForRequest(request())) |
467 return true; | 494 return true; |
468 | 495 |
469 controller()->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); | |
470 return false; | 496 return false; |
471 } | 497 } |
472 | 498 |
473 void MojoAsyncResourceHandler::OnWritable(MojoResult result) { | 499 void MojoAsyncResourceHandler::OnWritable(MojoResult result) { |
474 if (!did_defer_on_writing_) | 500 if (!did_defer_on_writing_) |
475 return; | 501 return; |
| 502 DCHECK(has_controller()); |
476 DCHECK(!did_defer_on_redirect_); | 503 DCHECK(!did_defer_on_redirect_); |
477 did_defer_on_writing_ = false; | 504 did_defer_on_writing_ = false; |
478 | 505 |
479 if (is_using_io_buffer_not_from_writer_) { | 506 if (is_using_io_buffer_not_from_writer_) { |
480 // |buffer_| is set to a net::IOBufferWithSize. Write the buffer contents | 507 // |buffer_| is set to a net::IOBufferWithSize. Write the buffer contents |
481 // to the data pipe. | 508 // to the data pipe. |
482 DCHECK_GT(buffer_bytes_read_, 0u); | 509 DCHECK_GT(buffer_bytes_read_, 0u); |
483 if (!CopyReadDataToDataPipe(&did_defer_on_writing_)) { | 510 if (!CopyReadDataToDataPipe(&did_defer_on_writing_)) { |
484 controller()->CancelWithError(net::ERR_FAILED); | 511 CancelWithError(net::ERR_FAILED); |
485 return; | 512 return; |
486 } | 513 } |
487 } else { | 514 } else { |
488 // Allocate a buffer for the next OnWillRead call here. | 515 // Allocate a buffer for the next OnWillRead call here. |
489 if (!AllocateWriterIOBuffer(&buffer_, &did_defer_on_writing_)) { | 516 if (!AllocateWriterIOBuffer(&buffer_, &did_defer_on_writing_)) { |
490 controller()->CancelWithError(net::ERR_FAILED); | 517 CancelWithError(net::ERR_FAILED); |
491 return; | 518 return; |
492 } | 519 } |
493 } | 520 } |
494 | 521 |
495 if (did_defer_on_writing_) { | 522 if (did_defer_on_writing_) { |
496 // Continue waiting. | 523 // Continue waiting. |
497 return; | 524 return; |
498 } | 525 } |
499 request()->LogUnblocked(); | 526 request()->LogUnblocked(); |
500 controller()->Resume(); | 527 Resume(); |
501 } | 528 } |
502 | 529 |
503 void MojoAsyncResourceHandler::Cancel() { | 530 void MojoAsyncResourceHandler::Cancel() { |
504 const ResourceRequestInfoImpl* info = GetRequestInfo(); | 531 const ResourceRequestInfoImpl* info = GetRequestInfo(); |
505 ResourceDispatcherHostImpl::Get()->CancelRequestFromRenderer( | 532 ResourceDispatcherHostImpl::Get()->CancelRequestFromRenderer( |
506 GlobalRequestID(info->GetChildID(), info->GetRequestID())); | 533 GlobalRequestID(info->GetChildID(), info->GetRequestID())); |
507 } | 534 } |
508 | 535 |
509 int64_t MojoAsyncResourceHandler::CalculateRecentlyReceivedBytes() { | 536 int64_t MojoAsyncResourceHandler::CalculateRecentlyReceivedBytes() { |
510 int64_t total_received_bytes = request()->GetTotalReceivedBytes(); | 537 int64_t total_received_bytes = request()->GetTotalReceivedBytes(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
544 base::Bind(&MojoAsyncResourceHandler::OnUploadProgressACK, | 571 base::Bind(&MojoAsyncResourceHandler::OnUploadProgressACK, |
545 weak_factory_.GetWeakPtr())); | 572 weak_factory_.GetWeakPtr())); |
546 } | 573 } |
547 | 574 |
548 void MojoAsyncResourceHandler::OnUploadProgressACK() { | 575 void MojoAsyncResourceHandler::OnUploadProgressACK() { |
549 if (upload_progress_tracker_) | 576 if (upload_progress_tracker_) |
550 upload_progress_tracker_->OnAckReceived(); | 577 upload_progress_tracker_->OnAckReceived(); |
551 } | 578 } |
552 | 579 |
553 } // namespace content | 580 } // namespace content |
OLD | NEW |