Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/web_url_loader_impl.h" | 5 #include "content/child/web_url_loader_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <deque> | |
| 9 #include <string> | 8 #include <string> |
| 10 | 9 |
| 11 #include "base/bind.h" | 10 #include "base/bind.h" |
| 12 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 13 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 14 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 15 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
| 16 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 17 #include "base/time/time.h" | 16 #include "base/time/time.h" |
| 18 #include "components/mime_util/mime_util.h" | 17 #include "components/mime_util/mime_util.h" |
| 19 #include "content/child/child_thread_impl.h" | 18 #include "content/child/child_thread_impl.h" |
| 20 #include "content/child/ftp_directory_listing_response_delegate.h" | 19 #include "content/child/ftp_directory_listing_response_delegate.h" |
| 21 #include "content/child/multipart_response_delegate.h" | 20 #include "content/child/multipart_response_delegate.h" |
| 22 #include "content/child/request_extra_data.h" | 21 #include "content/child/request_extra_data.h" |
| 23 #include "content/child/request_info.h" | 22 #include "content/child/request_info.h" |
| 24 #include "content/child/resource_dispatcher.h" | 23 #include "content/child/resource_dispatcher.h" |
| 24 #include "content/child/shared_memory_data_consumer_handle.h" | |
| 25 #include "content/child/sync_load_response.h" | 25 #include "content/child/sync_load_response.h" |
| 26 #include "content/child/web_data_consumer_handle_impl.h" | |
| 27 #include "content/child/web_url_request_util.h" | 26 #include "content/child/web_url_request_util.h" |
| 28 #include "content/child/weburlresponse_extradata_impl.h" | 27 #include "content/child/weburlresponse_extradata_impl.h" |
| 29 #include "content/common/resource_messages.h" | 28 #include "content/common/resource_messages.h" |
| 30 #include "content/common/resource_request_body.h" | 29 #include "content/common/resource_request_body.h" |
| 31 #include "content/common/service_worker/service_worker_types.h" | 30 #include "content/common/service_worker/service_worker_types.h" |
| 32 #include "content/public/child/fixed_received_data.h" | 31 #include "content/public/child/fixed_received_data.h" |
| 33 #include "content/public/child/request_peer.h" | 32 #include "content/public/child/request_peer.h" |
| 34 #include "content/public/common/content_switches.h" | 33 #include "content/public/common/content_switches.h" |
| 35 #include "net/base/data_url.h" | 34 #include "net/base/data_url.h" |
| 36 #include "net/base/filename_util.h" | 35 #include "net/base/filename_util.h" |
| 37 #include "net/base/net_errors.h" | 36 #include "net/base/net_errors.h" |
| 38 #include "net/http/http_response_headers.h" | 37 #include "net/http/http_response_headers.h" |
| 39 #include "net/http/http_util.h" | 38 #include "net/http/http_util.h" |
| 40 #include "net/url_request/redirect_info.h" | 39 #include "net/url_request/redirect_info.h" |
| 41 #include "net/url_request/url_request_data_job.h" | 40 #include "net/url_request/url_request_data_job.h" |
| 42 #include "third_party/WebKit/public/platform/WebHTTPLoadInfo.h" | 41 #include "third_party/WebKit/public/platform/WebHTTPLoadInfo.h" |
| 43 #include "third_party/WebKit/public/platform/WebURL.h" | 42 #include "third_party/WebKit/public/platform/WebURL.h" |
| 44 #include "third_party/WebKit/public/platform/WebURLError.h" | 43 #include "third_party/WebKit/public/platform/WebURLError.h" |
| 45 #include "third_party/WebKit/public/platform/WebURLLoadTiming.h" | 44 #include "third_party/WebKit/public/platform/WebURLLoadTiming.h" |
| 46 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" | 45 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" |
| 47 #include "third_party/WebKit/public/platform/WebURLRequest.h" | 46 #include "third_party/WebKit/public/platform/WebURLRequest.h" |
| 48 #include "third_party/WebKit/public/platform/WebURLResponse.h" | 47 #include "third_party/WebKit/public/platform/WebURLResponse.h" |
| 49 #include "third_party/WebKit/public/web/WebSecurityPolicy.h" | 48 #include "third_party/WebKit/public/web/WebSecurityPolicy.h" |
| 50 #include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" | |
| 51 | 49 |
| 52 using base::Time; | 50 using base::Time; |
| 53 using base::TimeTicks; | 51 using base::TimeTicks; |
| 54 using blink::WebData; | 52 using blink::WebData; |
| 55 using blink::WebHTTPBody; | 53 using blink::WebHTTPBody; |
| 56 using blink::WebHTTPHeaderVisitor; | 54 using blink::WebHTTPHeaderVisitor; |
| 57 using blink::WebHTTPLoadInfo; | 55 using blink::WebHTTPLoadInfo; |
| 58 using blink::WebReferrerPolicy; | 56 using blink::WebReferrerPolicy; |
| 59 using blink::WebSecurityPolicy; | 57 using blink::WebSecurityPolicy; |
| 60 using blink::WebString; | 58 using blink::WebString; |
| 61 using blink::WebURL; | 59 using blink::WebURL; |
| 62 using blink::WebURLError; | 60 using blink::WebURLError; |
| 63 using blink::WebURLLoadTiming; | 61 using blink::WebURLLoadTiming; |
| 64 using blink::WebURLLoader; | 62 using blink::WebURLLoader; |
| 65 using blink::WebURLLoaderClient; | 63 using blink::WebURLLoaderClient; |
| 66 using blink::WebURLRequest; | 64 using blink::WebURLRequest; |
| 67 using blink::WebURLResponse; | 65 using blink::WebURLResponse; |
| 68 | 66 |
| 69 namespace content { | 67 namespace content { |
| 70 | 68 |
| 71 // Utilities ------------------------------------------------------------------ | 69 // Utilities ------------------------------------------------------------------ |
| 72 | 70 |
| 73 namespace { | 71 namespace { |
| 74 | 72 |
| 75 const size_t kBodyStreamPipeCapacity = 4 * 1024; | |
| 76 | |
| 77 using HeadersVector = ResourceDevToolsInfo::HeadersVector; | 73 using HeadersVector = ResourceDevToolsInfo::HeadersVector; |
| 78 | 74 |
| 79 // Converts timing data from |load_timing| to the format used by WebKit. | 75 // Converts timing data from |load_timing| to the format used by WebKit. |
| 80 void PopulateURLLoadTiming(const net::LoadTimingInfo& load_timing, | 76 void PopulateURLLoadTiming(const net::LoadTimingInfo& load_timing, |
| 81 WebURLLoadTiming* url_timing) { | 77 WebURLLoadTiming* url_timing) { |
| 82 DCHECK(!load_timing.request_start.is_null()); | 78 DCHECK(!load_timing.request_start.is_null()); |
| 83 | 79 |
| 84 const TimeTicks kNullTicks; | 80 const TimeTicks kNullTicks; |
| 85 url_timing->initialize(); | 81 url_timing->initialize(); |
| 86 url_timing->setRequestTime( | 82 url_timing->setRequestTime( |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 const base::TimeTicks& completion_time, | 319 const base::TimeTicks& completion_time, |
| 324 int64 total_transfer_size) override; | 320 int64 total_transfer_size) override; |
| 325 | 321 |
| 326 private: | 322 private: |
| 327 friend class base::RefCounted<Context>; | 323 friend class base::RefCounted<Context>; |
| 328 ~Context() override; | 324 ~Context() override; |
| 329 | 325 |
| 330 // We can optimize the handling of data URLs in most cases. | 326 // We can optimize the handling of data URLs in most cases. |
| 331 bool CanHandleDataURLRequestLocally() const; | 327 bool CanHandleDataURLRequestLocally() const; |
| 332 void HandleDataURL(); | 328 void HandleDataURL(); |
| 333 MojoResult WriteDataOnBodyStream(const char* data, size_t size); | |
| 334 void OnHandleGotWritable(MojoResult); | |
| 335 | 329 |
| 336 WebURLLoaderImpl* loader_; | 330 WebURLLoaderImpl* loader_; |
| 337 WebURLRequest request_; | 331 WebURLRequest request_; |
| 338 WebURLLoaderClient* client_; | 332 WebURLLoaderClient* client_; |
| 339 ResourceDispatcher* resource_dispatcher_; | 333 ResourceDispatcher* resource_dispatcher_; |
| 340 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 334 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 341 WebReferrerPolicy referrer_policy_; | 335 WebReferrerPolicy referrer_policy_; |
| 342 scoped_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_; | 336 scoped_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_; |
| 343 scoped_ptr<MultipartResponseDelegate> multipart_delegate_; | 337 scoped_ptr<MultipartResponseDelegate> multipart_delegate_; |
| 344 scoped_ptr<StreamOverrideParameters> stream_override_; | 338 scoped_ptr<StreamOverrideParameters> stream_override_; |
| 345 mojo::ScopedDataPipeProducerHandle body_stream_writer_; | 339 scoped_ptr<SharedMemoryDataConsumerHandle::Writer> body_stream_writer_; |
| 346 mojo::common::HandleWatcher body_stream_writer_watcher_; | |
| 347 // TODO(yhirano): Delete this buffer after implementing the back-pressure | |
| 348 // mechanism. | |
| 349 std::deque<char> body_stream_buffer_; | |
| 350 bool got_all_stream_body_data_; | |
| 351 enum DeferState {NOT_DEFERRING, SHOULD_DEFER, DEFERRED_DATA}; | 340 enum DeferState {NOT_DEFERRING, SHOULD_DEFER, DEFERRED_DATA}; |
| 352 DeferState defers_loading_; | 341 DeferState defers_loading_; |
| 353 int request_id_; | 342 int request_id_; |
| 354 }; | 343 }; |
| 355 | 344 |
| 356 WebURLLoaderImpl::Context::Context( | 345 WebURLLoaderImpl::Context::Context( |
| 357 WebURLLoaderImpl* loader, | 346 WebURLLoaderImpl* loader, |
| 358 ResourceDispatcher* resource_dispatcher, | 347 ResourceDispatcher* resource_dispatcher, |
| 359 scoped_refptr<base::SingleThreadTaskRunner> task_runner) | 348 scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
| 360 : loader_(loader), | 349 : loader_(loader), |
| 361 client_(NULL), | 350 client_(NULL), |
| 362 resource_dispatcher_(resource_dispatcher), | 351 resource_dispatcher_(resource_dispatcher), |
| 363 task_runner_(task_runner), | 352 task_runner_(task_runner), |
| 364 referrer_policy_(blink::WebReferrerPolicyDefault), | 353 referrer_policy_(blink::WebReferrerPolicyDefault), |
| 365 got_all_stream_body_data_(false), | |
| 366 defers_loading_(NOT_DEFERRING), | 354 defers_loading_(NOT_DEFERRING), |
| 367 request_id_(-1) { | 355 request_id_(-1) { |
| 368 } | 356 } |
| 369 | 357 |
| 370 void WebURLLoaderImpl::Context::Cancel() { | 358 void WebURLLoaderImpl::Context::Cancel() { |
| 371 if (resource_dispatcher_ && // NULL in unittest. | 359 if (resource_dispatcher_ && // NULL in unittest. |
| 372 request_id_ != -1) { | 360 request_id_ != -1) { |
| 373 resource_dispatcher_->Cancel(request_id_); | 361 resource_dispatcher_->Cancel(request_id_); |
| 374 request_id_ = -1; | 362 request_id_ = -1; |
| 375 } | 363 } |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 612 response.setMIMEType("text/html"); | 600 response.setMIMEType("text/html"); |
| 613 } | 601 } |
| 614 } | 602 } |
| 615 | 603 |
| 616 // Prevent |this| from being destroyed if the client destroys the loader, | 604 // Prevent |this| from being destroyed if the client destroys the loader, |
| 617 // ether in didReceiveResponse, or when the multipart/ftp delegate calls into | 605 // ether in didReceiveResponse, or when the multipart/ftp delegate calls into |
| 618 // it. | 606 // it. |
| 619 scoped_refptr<Context> protect(this); | 607 scoped_refptr<Context> protect(this); |
| 620 | 608 |
| 621 if (request_.useStreamOnResponse()) { | 609 if (request_.useStreamOnResponse()) { |
| 622 MojoCreateDataPipeOptions options; | 610 SharedMemoryDataConsumerHandle::BackpressureMode mode = |
| 623 options.struct_size = sizeof(MojoCreateDataPipeOptions); | 611 SharedMemoryDataConsumerHandle::kDoNotApplyBackpressure; |
| 624 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; | 612 if (info.headers && |
| 625 options.element_num_bytes = 1; | 613 info.headers->HasHeaderValue("Cache-Control", "no-store")) { |
| 626 options.capacity_num_bytes = kBodyStreamPipeCapacity; | 614 mode = SharedMemoryDataConsumerHandle::kApplyBackpressure; |
| 615 } | |
| 627 | 616 |
| 628 mojo::ScopedDataPipeConsumerHandle consumer; | 617 auto reader = make_scoped_ptr( |
| 629 MojoResult result = mojo::CreateDataPipe(&options, | 618 new SharedMemoryDataConsumerHandle(mode, &body_stream_writer_)); |
| 630 &body_stream_writer_, | 619 |
| 631 &consumer); | 620 // The client takes |reader|'s ownership. |
| 632 if (result != MOJO_RESULT_OK) { | 621 client_->didReceiveResponse(loader_, response, reader.release()); |
|
tyoshino (SeeGerritForStatus)
2015/06/10 13:45:55
how about skipping the rest of this function until
yhirano
2015/06/11 02:17:00
Done.
| |
| 633 // TODO(yhirano): Handle the error. | |
| 634 return; | |
| 635 } | |
| 636 client_->didReceiveResponse( | |
| 637 loader_, response, new WebDataConsumerHandleImpl(consumer.Pass())); | |
| 638 } else { | 622 } else { |
| 639 client_->didReceiveResponse(loader_, response); | 623 client_->didReceiveResponse(loader_, response); |
| 640 } | 624 } |
| 641 | 625 |
| 642 // We may have been cancelled after didReceiveResponse, which would leave us | 626 // We may have been cancelled after didReceiveResponse, which would leave us |
| 643 // without a client and therefore without much need to do further handling. | 627 // without a client and therefore without much need to do further handling. |
| 644 if (!client_) | 628 if (!client_) |
| 645 return; | 629 return; |
| 646 | 630 |
| 647 DCHECK(!ftp_listing_delegate_.get()); | 631 DCHECK(!ftp_listing_delegate_.get()); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 677 client_->didDownloadData(loader_, len, encoded_data_length); | 661 client_->didDownloadData(loader_, len, encoded_data_length); |
| 678 } | 662 } |
| 679 | 663 |
| 680 void WebURLLoaderImpl::Context::OnReceivedData(scoped_ptr<ReceivedData> data) { | 664 void WebURLLoaderImpl::Context::OnReceivedData(scoped_ptr<ReceivedData> data) { |
| 681 const char* payload = data->payload(); | 665 const char* payload = data->payload(); |
| 682 int data_length = data->length(); | 666 int data_length = data->length(); |
| 683 int encoded_data_length = data->encoded_length(); | 667 int encoded_data_length = data->encoded_length(); |
| 684 if (!client_) | 668 if (!client_) |
| 685 return; | 669 return; |
| 686 | 670 |
| 687 if (request_.useStreamOnResponse()) { | 671 if (ftp_listing_delegate_) { |
| 688 // We don't support ftp_listening_delegate_ and multipart_delegate_ for now. | |
| 689 // TODO(yhirano): Support ftp listening and multipart. | |
| 690 MojoResult rv = WriteDataOnBodyStream(payload, data_length); | |
| 691 if (rv != MOJO_RESULT_OK && client_) { | |
| 692 client_->didFail( | |
| 693 loader_, CreateWebURLError(request_.url(), false, net::ERR_FAILED)); | |
| 694 } | |
| 695 } else if (ftp_listing_delegate_) { | |
| 696 // The FTP listing delegate will make the appropriate calls to | 672 // The FTP listing delegate will make the appropriate calls to |
| 697 // client_->didReceiveData and client_->didReceiveResponse. Since the | 673 // client_->didReceiveData and client_->didReceiveResponse. Since the |
| 698 // delegate may want to do work after sending data to the delegate, keep | 674 // delegate may want to do work after sending data to the delegate, keep |
| 699 // |this| and the delegate alive until it's finished handling the data. | 675 // |this| and the delegate alive until it's finished handling the data. |
| 700 scoped_refptr<Context> protect(this); | 676 scoped_refptr<Context> protect(this); |
| 701 ftp_listing_delegate_->OnReceivedData(payload, data_length); | 677 ftp_listing_delegate_->OnReceivedData(payload, data_length); |
| 702 } else if (multipart_delegate_) { | 678 } else if (multipart_delegate_) { |
| 703 // The multipart delegate will make the appropriate calls to | 679 // The multipart delegate will make the appropriate calls to |
| 704 // client_->didReceiveData and client_->didReceiveResponse. Since the | 680 // client_->didReceiveData and client_->didReceiveResponse. Since the |
| 705 // delegate may want to do work after sending data to the delegate, keep | 681 // delegate may want to do work after sending data to the delegate, keep |
| 706 // |this| and the delegate alive until it's finished handling the data. | 682 // |this| and the delegate alive until it's finished handling the data. |
| 707 scoped_refptr<Context> protect(this); | 683 scoped_refptr<Context> protect(this); |
| 708 multipart_delegate_->OnReceivedData(payload, data_length, | 684 multipart_delegate_->OnReceivedData(payload, data_length, |
| 709 encoded_data_length); | 685 encoded_data_length); |
| 710 } else { | 686 } else { |
| 687 scoped_refptr<Context> protect(this); | |
| 688 // We dispatch the data even when |useStreamOnResponse()| is set, in order | |
| 689 // to make Devtools work. | |
| 711 client_->didReceiveData(loader_, payload, data_length, encoded_data_length); | 690 client_->didReceiveData(loader_, payload, data_length, encoded_data_length); |
| 691 | |
| 692 if (request_.useStreamOnResponse()) { | |
| 693 // We don't support ftp_listening_delegate_ and multipart_delegate_ for | |
| 694 // now. | |
| 695 // TODO(yhirano): Support ftp listening and multipart. | |
| 696 body_stream_writer_->AddData(data.Pass()); | |
| 697 } | |
| 712 } | 698 } |
| 713 } | 699 } |
| 714 | 700 |
| 715 void WebURLLoaderImpl::Context::OnReceivedCachedMetadata( | 701 void WebURLLoaderImpl::Context::OnReceivedCachedMetadata( |
| 716 const char* data, int len) { | 702 const char* data, int len) { |
| 717 if (client_) | 703 if (client_) |
| 718 client_->didReceiveCachedMetadata(loader_, data, len); | 704 client_->didReceiveCachedMetadata(loader_, data, len); |
| 719 } | 705 } |
| 720 | 706 |
| 721 void WebURLLoaderImpl::Context::OnCompletedRequest( | 707 void WebURLLoaderImpl::Context::OnCompletedRequest( |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 734 if (ftp_listing_delegate_) { | 720 if (ftp_listing_delegate_) { |
| 735 ftp_listing_delegate_->OnCompletedRequest(); | 721 ftp_listing_delegate_->OnCompletedRequest(); |
| 736 ftp_listing_delegate_.reset(NULL); | 722 ftp_listing_delegate_.reset(NULL); |
| 737 } else if (multipart_delegate_) { | 723 } else if (multipart_delegate_) { |
| 738 multipart_delegate_->OnCompletedRequest(); | 724 multipart_delegate_->OnCompletedRequest(); |
| 739 multipart_delegate_.reset(NULL); | 725 multipart_delegate_.reset(NULL); |
| 740 } | 726 } |
| 741 | 727 |
| 742 if (client_) { | 728 if (client_) { |
| 743 if (error_code != net::OK) { | 729 if (error_code != net::OK) { |
| 744 client_->didFail( | 730 client_->didFail( |
|
hiroshige
2015/06/11 00:58:00
We have to pass failures to |body_stream_writer_|/
yhirano
2015/06/11 02:17:00
I have another WIP CL addressing this issue: https
| |
| 745 loader_, | 731 loader_, |
| 746 CreateWebURLError(request_.url(), stale_copy_in_cache, error_code)); | 732 CreateWebURLError(request_.url(), stale_copy_in_cache, error_code)); |
| 747 } else { | 733 } else { |
| 748 if (request_.useStreamOnResponse()) { | 734 if (request_.useStreamOnResponse()) |
| 749 got_all_stream_body_data_ = true; | 735 body_stream_writer_.reset(); |
| 750 if (body_stream_buffer_.empty()) { | 736 |
| 751 // Close the handle to notify the end of data. | 737 client_->didFinishLoading(loader_, |
|
hiroshige
2015/06/11 00:01:58
Here |client_| can be null and |if(client_)| is ne
yhirano
2015/06/11 02:17:00
Done.
| |
| 752 body_stream_writer_.reset(); | 738 (completion_time - TimeTicks()).InSecondsF(), |
| 753 client_->didFinishLoading( | 739 total_transfer_size); |
| 754 loader_, (completion_time - TimeTicks()).InSecondsF(), | |
| 755 total_transfer_size); | |
| 756 } | |
| 757 } else { | |
| 758 client_->didFinishLoading( | |
| 759 loader_, (completion_time - TimeTicks()).InSecondsF(), | |
| 760 total_transfer_size); | |
| 761 } | |
| 762 } | 740 } |
| 763 } | 741 } |
| 764 } | 742 } |
| 765 | 743 |
| 766 WebURLLoaderImpl::Context::~Context() { | 744 WebURLLoaderImpl::Context::~Context() { |
| 767 if (request_id_ >= 0) { | 745 if (request_id_ >= 0) { |
| 768 resource_dispatcher_->RemovePendingRequest(request_id_); | 746 resource_dispatcher_->RemovePendingRequest(request_id_); |
| 769 } | 747 } |
| 770 } | 748 } |
| 771 | 749 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 826 OnReceivedResponse(info); | 804 OnReceivedResponse(info); |
| 827 if (!data.empty()) | 805 if (!data.empty()) |
| 828 OnReceivedData( | 806 OnReceivedData( |
| 829 make_scoped_ptr(new FixedReceivedData(data.data(), data.size(), 0))); | 807 make_scoped_ptr(new FixedReceivedData(data.data(), data.size(), 0))); |
| 830 } | 808 } |
| 831 | 809 |
| 832 OnCompletedRequest(error_code, false, false, info.security_info, | 810 OnCompletedRequest(error_code, false, false, info.security_info, |
| 833 base::TimeTicks::Now(), 0); | 811 base::TimeTicks::Now(), 0); |
| 834 } | 812 } |
| 835 | 813 |
| 836 MojoResult WebURLLoaderImpl::Context::WriteDataOnBodyStream(const char* data, | |
| 837 size_t size) { | |
| 838 if (body_stream_buffer_.empty() && size == 0) { | |
| 839 // Nothing to do. | |
| 840 return MOJO_RESULT_OK; | |
| 841 } | |
| 842 | |
| 843 if (!body_stream_writer_.is_valid()) { | |
| 844 // The handle is already cleared. | |
| 845 return MOJO_RESULT_OK; | |
| 846 } | |
| 847 | |
| 848 char* buffer = nullptr; | |
| 849 uint32_t num_bytes_writable = 0; | |
| 850 MojoResult rv = mojo::BeginWriteDataRaw(body_stream_writer_.get(), | |
| 851 reinterpret_cast<void**>(&buffer), | |
| 852 &num_bytes_writable, | |
| 853 MOJO_WRITE_DATA_FLAG_NONE); | |
| 854 if (rv == MOJO_RESULT_SHOULD_WAIT) { | |
| 855 body_stream_buffer_.insert(body_stream_buffer_.end(), data, data + size); | |
| 856 body_stream_writer_watcher_.Start( | |
| 857 body_stream_writer_.get(), | |
| 858 MOJO_HANDLE_SIGNAL_WRITABLE, | |
| 859 MOJO_DEADLINE_INDEFINITE, | |
| 860 base::Bind(&WebURLLoaderImpl::Context::OnHandleGotWritable, | |
| 861 base::Unretained(this))); | |
| 862 return MOJO_RESULT_OK; | |
| 863 } | |
| 864 | |
| 865 if (rv != MOJO_RESULT_OK) | |
| 866 return rv; | |
| 867 | |
| 868 uint32_t num_bytes_to_write = 0; | |
| 869 if (num_bytes_writable < body_stream_buffer_.size()) { | |
| 870 auto begin = body_stream_buffer_.begin(); | |
| 871 auto end = body_stream_buffer_.begin() + num_bytes_writable; | |
| 872 | |
| 873 std::copy(begin, end, buffer); | |
| 874 num_bytes_to_write = num_bytes_writable; | |
| 875 body_stream_buffer_.erase(begin, end); | |
| 876 body_stream_buffer_.insert(body_stream_buffer_.end(), data, data + size); | |
| 877 } else { | |
| 878 std::copy(body_stream_buffer_.begin(), body_stream_buffer_.end(), buffer); | |
| 879 num_bytes_writable -= body_stream_buffer_.size(); | |
| 880 num_bytes_to_write += body_stream_buffer_.size(); | |
| 881 buffer += body_stream_buffer_.size(); | |
| 882 body_stream_buffer_.clear(); | |
| 883 | |
| 884 size_t num_newbytes_to_write = | |
| 885 std::min(size, static_cast<size_t>(num_bytes_writable)); | |
| 886 std::copy(data, data + num_newbytes_to_write, buffer); | |
| 887 num_bytes_to_write += num_newbytes_to_write; | |
| 888 body_stream_buffer_.insert(body_stream_buffer_.end(), | |
| 889 data + num_newbytes_to_write, | |
| 890 data + size); | |
| 891 } | |
| 892 | |
| 893 rv = mojo::EndWriteDataRaw(body_stream_writer_.get(), num_bytes_to_write); | |
| 894 if (rv == MOJO_RESULT_OK && !body_stream_buffer_.empty()) { | |
| 895 body_stream_writer_watcher_.Start( | |
| 896 body_stream_writer_.get(), | |
| 897 MOJO_HANDLE_SIGNAL_WRITABLE, | |
| 898 MOJO_DEADLINE_INDEFINITE, | |
| 899 base::Bind(&WebURLLoaderImpl::Context::OnHandleGotWritable, | |
| 900 base::Unretained(this))); | |
| 901 } | |
| 902 return rv; | |
| 903 } | |
| 904 | |
| 905 void WebURLLoaderImpl::Context::OnHandleGotWritable(MojoResult result) { | |
| 906 if (result != MOJO_RESULT_OK) { | |
| 907 if (client_) { | |
| 908 client_->didFail( | |
| 909 loader_, CreateWebURLError(request_.url(), false, net::ERR_FAILED)); | |
| 910 // |this| can be deleted here. | |
| 911 } | |
| 912 return; | |
| 913 } | |
| 914 | |
| 915 if (body_stream_buffer_.empty()) | |
| 916 return; | |
| 917 | |
| 918 MojoResult rv = WriteDataOnBodyStream(nullptr, 0); | |
| 919 if (rv == MOJO_RESULT_OK) { | |
| 920 if (got_all_stream_body_data_ && body_stream_buffer_.empty()) { | |
| 921 // Close the handle to notify the end of data. | |
| 922 body_stream_writer_.reset(); | |
| 923 if (client_) { | |
| 924 // TODO(yhirano): Pass appropriate arguments. | |
| 925 client_->didFinishLoading(loader_, 0, 0); | |
| 926 // |this| can be deleted here. | |
| 927 } | |
| 928 } | |
| 929 } else { | |
| 930 if (client_) { | |
| 931 client_->didFail( | |
| 932 loader_, CreateWebURLError(request_.url(), false, net::ERR_FAILED)); | |
| 933 // |this| can be deleted here. | |
| 934 } | |
| 935 } | |
| 936 } | |
| 937 | |
| 938 // WebURLLoaderImpl ----------------------------------------------------------- | 814 // WebURLLoaderImpl ----------------------------------------------------------- |
| 939 | 815 |
| 940 WebURLLoaderImpl::WebURLLoaderImpl( | 816 WebURLLoaderImpl::WebURLLoaderImpl( |
| 941 ResourceDispatcher* resource_dispatcher, | 817 ResourceDispatcher* resource_dispatcher, |
| 942 scoped_refptr<base::SingleThreadTaskRunner> task_runner) | 818 scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
| 943 : context_(new Context(this, resource_dispatcher, task_runner)) { | 819 : context_(new Context(this, resource_dispatcher, task_runner)) { |
| 944 } | 820 } |
| 945 | 821 |
| 946 WebURLLoaderImpl::~WebURLLoaderImpl() { | 822 WebURLLoaderImpl::~WebURLLoaderImpl() { |
| 947 cancel(); | 823 cancel(); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1115 int intra_priority_value) { | 991 int intra_priority_value) { |
| 1116 context_->DidChangePriority(new_priority, intra_priority_value); | 992 context_->DidChangePriority(new_priority, intra_priority_value); |
| 1117 } | 993 } |
| 1118 | 994 |
| 1119 bool WebURLLoaderImpl::attachThreadedDataReceiver( | 995 bool WebURLLoaderImpl::attachThreadedDataReceiver( |
| 1120 blink::WebThreadedDataReceiver* threaded_data_receiver) { | 996 blink::WebThreadedDataReceiver* threaded_data_receiver) { |
| 1121 return context_->AttachThreadedDataReceiver(threaded_data_receiver); | 997 return context_->AttachThreadedDataReceiver(threaded_data_receiver); |
| 1122 } | 998 } |
| 1123 | 999 |
| 1124 } // namespace content | 1000 } // namespace content |
| OLD | NEW |