Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(241)

Side by Side Diff: net/url_request/url_request_job.cc

Issue 1662763002: [ON HOLD] Implement pull-based design for content decoding (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebased Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/url_request/url_request_job.h ('k') | net/url_request/url_request_job_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "net/url_request/url_request_job.h" 5 #include "net/url_request/url_request_job.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
10 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
11 #include "base/location.h" 12 #include "base/location.h"
13 #include "base/memory/ptr_util.h"
12 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
13 #include "base/power_monitor/power_monitor.h" 15 #include "base/power_monitor/power_monitor.h"
14 #include "base/profiler/scoped_tracker.h" 16 #include "base/profiler/scoped_tracker.h"
15 #include "base/single_thread_task_runner.h" 17 #include "base/single_thread_task_runner.h"
16 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_split.h" 19 #include "base/strings/string_split.h"
18 #include "base/strings/string_util.h" 20 #include "base/strings/string_util.h"
19 #include "base/threading/thread_task_runner_handle.h" 21 #include "base/threading/thread_task_runner_handle.h"
20 #include "base/values.h" 22 #include "base/values.h"
21 #include "net/base/auth.h" 23 #include "net/base/auth.h"
22 #include "net/base/host_port_pair.h" 24 #include "net/base/host_port_pair.h"
23 #include "net/base/io_buffer.h" 25 #include "net/base/io_buffer.h"
24 #include "net/base/load_flags.h" 26 #include "net/base/load_flags.h"
25 #include "net/base/load_states.h" 27 #include "net/base/load_states.h"
26 #include "net/base/net_errors.h" 28 #include "net/base/net_errors.h"
27 #include "net/base/network_delegate.h" 29 #include "net/base/network_delegate.h"
28 #include "net/filter/filter.h"
29 #include "net/http/http_response_headers.h" 30 #include "net/http/http_response_headers.h"
30 #include "net/nqe/network_quality_estimator.h" 31 #include "net/nqe/network_quality_estimator.h"
31 #include "net/url_request/url_request_context.h" 32 #include "net/url_request/url_request_context.h"
32 33
33 namespace net { 34 namespace net {
34 35
35 namespace { 36 namespace {
36 37
37 // Callback for TYPE_URL_REQUEST_FILTERS_SET net-internals event. 38 // Callback for TYPE_URL_REQUEST_FILTERS_SET net-internals event.
38 std::unique_ptr<base::Value> FiltersSetCallback( 39 std::unique_ptr<base::Value> SourceStreamSetCallback(
39 Filter* filter, 40 SourceStream* source_stream,
40 NetLogCaptureMode /* capture_mode */) { 41 NetLogCaptureMode /* capture_mode */) {
41 std::unique_ptr<base::DictionaryValue> event_params( 42 std::unique_ptr<base::DictionaryValue> event_params(
42 new base::DictionaryValue()); 43 new base::DictionaryValue());
43 event_params->SetString("filters", filter->OrderedFilterList()); 44 event_params->SetString("filters", source_stream->OrderedTypeStringList());
44 return std::move(event_params); 45 return std::move(event_params);
45 } 46 }
46 47
47 std::string ComputeMethodForRedirect(const std::string& method, 48 std::string ComputeMethodForRedirect(const std::string& method,
48 int http_status_code) { 49 int http_status_code) {
49 // For 303 redirects, all request methods except HEAD are converted to GET, 50 // For 303 redirects, all request methods except HEAD are converted to GET,
50 // as per the latest httpbis draft. The draft also allows POST requests to 51 // as per the latest httpbis draft. The draft also allows POST requests to
51 // be converted to GETs when following 301/302 redirects, for historical 52 // be converted to GETs when following 301/302 redirects, for historical
52 // reasons. Most major browsers do this and so shall we. Both RFC 2616 and 53 // reasons. Most major browsers do this and so shall we. Both RFC 2616 and
53 // the httpbis draft say to prompt the user to confirm the generation of new 54 // the httpbis draft say to prompt the user to confirm the generation of new
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 base::CompareCaseInsensitiveASCII(token, "unsafe-url") == 0) { 109 base::CompareCaseInsensitiveASCII(token, "unsafe-url") == 0) {
109 new_policy = URLRequest::NEVER_CLEAR_REFERRER; 110 new_policy = URLRequest::NEVER_CLEAR_REFERRER;
110 continue; 111 continue;
111 } 112 }
112 } 113 }
113 return new_policy; 114 return new_policy;
114 } 115 }
115 116
116 } // namespace 117 } // namespace
117 118
119 // Each SourceStreams own the previous SourceStream in the chain, but the
120 // ultimate source is URLRequestJob, which has other ownership semantics, so
121 // this class is a proxy for URLRequestJob that is owned by the first stream
122 // (in dataflow order).
123 class URLRequestJob::URLRequestJobSourceStream : public SourceStream {
124 public:
125 explicit URLRequestJobSourceStream(URLRequestJob* job)
126 : SourceStream(SourceStream::TYPE_NONE), job_(job) {
127 DCHECK(job_);
128 }
129
130 ~URLRequestJobSourceStream() override {}
131
132 // SourceStream implementation:
133 int Read(IOBuffer* dest_buffer,
134 size_t buffer_size,
135 const CompletionCallback& callback) override {
136 DCHECK(job_);
137 return job_->ReadRawDataHelper(dest_buffer, buffer_size, callback);
138 }
139
140 std::string OrderedTypeStringList() const override { return ""; }
141
142 private:
143 // It is safe to keep a raw pointer because |job_| owns the last stream which
144 // indirectly owns |this|. Therefore, |job_| will not be destroyed when |this|
145 // is alive.
146 URLRequestJob* const job_;
147
148 DISALLOW_COPY_AND_ASSIGN(URLRequestJobSourceStream);
149 };
150
118 URLRequestJob::URLRequestJob(URLRequest* request, 151 URLRequestJob::URLRequestJob(URLRequest* request,
119 NetworkDelegate* network_delegate) 152 NetworkDelegate* network_delegate)
120 : request_(request), 153 : request_(request),
121 done_(false), 154 done_(false),
122 prefilter_bytes_read_(0), 155 prefilter_bytes_read_(0),
123 postfilter_bytes_read_(0), 156 postfilter_bytes_read_(0),
124 filter_needs_more_output_space_(false),
125 filtered_read_buffer_len_(0),
126 has_handled_response_(false), 157 has_handled_response_(false),
127 expected_content_size_(-1), 158 expected_content_size_(-1),
128 network_delegate_(network_delegate), 159 network_delegate_(network_delegate),
129 last_notified_total_received_bytes_(0), 160 last_notified_total_received_bytes_(0),
130 last_notified_total_sent_bytes_(0), 161 last_notified_total_sent_bytes_(0),
131 weak_factory_(this) { 162 weak_factory_(this) {
132 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); 163 base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
133 if (power_monitor) 164 if (power_monitor)
134 power_monitor->AddObserver(this); 165 power_monitor->AddObserver(this);
135 } 166 }
(...skipping 20 matching lines...) Expand all
156 // Kill(). 187 // Kill().
157 // TODO(mmenke): The URLRequest is currently deleted before this method 188 // TODO(mmenke): The URLRequest is currently deleted before this method
158 // invokes its async callback whenever this is called by the URLRequest. 189 // invokes its async callback whenever this is called by the URLRequest.
159 // Try to simplify how cancellation works. 190 // Try to simplify how cancellation works.
160 NotifyCanceled(); 191 NotifyCanceled();
161 } 192 }
162 193
163 // This function calls ReadRawData to get stream data. If a filter exists, it 194 // This function calls ReadRawData to get stream data. If a filter exists, it
164 // passes the data to the attached filter. It then returns the output from 195 // passes the data to the attached filter. It then returns the output from
165 // filter back to the caller. 196 // filter back to the caller.
197 // This method passes reads down the filter chain, where they eventually end up
198 // at URLRequestJobSourceStream::Read, which calls back into
199 // URLRequestJob::ReadRawData.
166 bool URLRequestJob::Read(IOBuffer* buf, int buf_size, int *bytes_read) { 200 bool URLRequestJob::Read(IOBuffer* buf, int buf_size, int *bytes_read) {
167 DCHECK_LT(buf_size, 1000000); // Sanity check. 201 DCHECK_LT(buf_size, 1000000); // Sanity check.
168 DCHECK(buf); 202 DCHECK(buf);
169 DCHECK(bytes_read); 203 DCHECK(bytes_read);
170 DCHECK(!filtered_read_buffer_);
171 DCHECK_EQ(0, filtered_read_buffer_len_);
172
173 Error error = OK;
174 *bytes_read = 0; 204 *bytes_read = 0;
175 205
176 // Skip Filter if not present. 206 pending_read_buffer_ = buf;
177 if (!filter_) { 207 int result = source_stream_->Read(
178 error = ReadRawDataHelper(buf, buf_size, bytes_read); 208 buf, buf_size, base::Bind(&URLRequestJob::SourceStreamReadComplete,
179 } else { 209 weak_factory_.GetWeakPtr(), false));
180 // Save the caller's buffers while we do IO 210 if (result == ERR_IO_PENDING) {
181 // in the filter's buffers. 211 SetStatus(URLRequestStatus::FromError(ERR_IO_PENDING));
182 filtered_read_buffer_ = buf; 212 return false;
183 filtered_read_buffer_len_ = buf_size;
184
185 error = ReadFilteredData(bytes_read);
186
187 // Synchronous EOF from the filter.
188 if (error == OK && *bytes_read == 0)
189 DoneReading();
190 } 213 }
191 214
192 if (error == OK) { 215 SourceStreamReadComplete(true, result);
193 // If URLRequestJob read zero bytes, the job is at EOF. 216
194 if (*bytes_read == 0) 217 if (result > 0)
195 NotifyDone(URLRequestStatus()); 218 *bytes_read = result;
196 } else if (error == ERR_IO_PENDING) { 219
197 SetStatus(URLRequestStatus::FromError(ERR_IO_PENDING)); 220 return result >= OK;
198 } else {
199 NotifyDone(URLRequestStatus::FromError(error));
200 *bytes_read = -1;
201 }
202 return error == OK;
203 } 221 }
204 222
205 void URLRequestJob::StopCaching() { 223 void URLRequestJob::StopCaching() {
206 // Nothing to do here. 224 // Nothing to do here.
207 } 225 }
208 226
209 bool URLRequestJob::GetFullRequestHeaders(HttpRequestHeaders* headers) const { 227 bool URLRequestJob::GetFullRequestHeaders(HttpRequestHeaders* headers) const {
210 // Most job types don't send request headers. 228 // Most job types don't send request headers.
211 return false; 229 return false;
212 } 230 }
(...skipping 26 matching lines...) Expand all
239 } 257 }
240 258
241 bool URLRequestJob::GetRemoteEndpoint(IPEndPoint* endpoint) const { 259 bool URLRequestJob::GetRemoteEndpoint(IPEndPoint* endpoint) const {
242 return false; 260 return false;
243 } 261 }
244 262
245 void URLRequestJob::PopulateNetErrorDetails(NetErrorDetails* details) const { 263 void URLRequestJob::PopulateNetErrorDetails(NetErrorDetails* details) const {
246 return; 264 return;
247 } 265 }
248 266
249 std::unique_ptr<Filter> URLRequestJob::SetupFilter() const {
250 return nullptr;
251 }
252
253 bool URLRequestJob::IsRedirectResponse(GURL* location, 267 bool URLRequestJob::IsRedirectResponse(GURL* location,
254 int* http_status_code) { 268 int* http_status_code) {
255 // For non-HTTP jobs, headers will be null. 269 // For non-HTTP jobs, headers will be null.
256 HttpResponseHeaders* headers = request_->response_headers(); 270 HttpResponseHeaders* headers = request_->response_headers();
257 if (!headers) 271 if (!headers)
258 return false; 272 return false;
259 273
260 std::string value; 274 std::string value;
261 if (!headers->IsRedirect(&value)) 275 if (!headers->IsRedirect(&value))
262 return false; 276 return false;
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 // Need to check for a NULL auth_info because the server may have failed 503 // Need to check for a NULL auth_info because the server may have failed
490 // to send a challenge with the 401 response. 504 // to send a challenge with the 401 response.
491 if (auth_info.get()) { 505 if (auth_info.get()) {
492 request_->NotifyAuthRequired(auth_info.get()); 506 request_->NotifyAuthRequired(auth_info.get());
493 // Wait for SetAuth or CancelAuth to be called. 507 // Wait for SetAuth or CancelAuth to be called.
494 return; 508 return;
495 } 509 }
496 } 510 }
497 511
498 has_handled_response_ = true; 512 has_handled_response_ = true;
499 if (request_->status().is_success()) 513 if (request_->status().is_success()) {
500 filter_ = SetupFilter(); 514 DCHECK(!source_stream_);
515 source_stream_ = SetUpSourceStream();
501 516
502 if (!filter_.get()) { 517 if (source_stream_ == nullptr) {
503 std::string content_length; 518 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
504 request_->GetResponseHeaderByName("content-length", &content_length); 519 ERR_CONTENT_DECODING_INIT_FAILED));
505 if (!content_length.empty()) 520 return;
506 base::StringToInt64(content_length, &expected_content_size_); 521 }
507 } else { 522
508 request_->net_log().AddEvent( 523 if (source_stream_->type() == SourceStream::TYPE_NONE) {
509 NetLog::TYPE_URL_REQUEST_FILTERS_SET, 524 std::string content_length;
510 base::Bind(&FiltersSetCallback, base::Unretained(filter_.get()))); 525 request_->GetResponseHeaderByName("content-length", &content_length);
526 if (!content_length.empty())
527 base::StringToInt64(content_length, &expected_content_size_);
528 } else {
529 request_->net_log().AddEvent(
530 NetLog::TYPE_URL_REQUEST_FILTERS_SET,
531 base::Bind(&SourceStreamSetCallback,
532 base::Unretained(source_stream_.get())));
533 }
511 } 534 }
512 535
513 request_->NotifyResponseStarted(); 536 request_->NotifyResponseStarted();
514 537
515 // |this| may be destroyed at this point. 538 // |this| may be destroyed at this point.
516 } 539 }
517 540
518 void URLRequestJob::ConvertResultToError(int result, Error* error, int* count) { 541 void URLRequestJob::ConvertResultToError(int result, Error* error, int* count) {
519 if (result >= 0) { 542 if (result >= 0) {
520 *error = OK; 543 *error = OK;
521 *count = result; 544 *count = result;
522 } else { 545 } else {
523 *error = static_cast<Error>(result); 546 *error = static_cast<Error>(result);
524 *count = 0; 547 *count = 0;
525 } 548 }
526 } 549 }
527 550
528 void URLRequestJob::ReadRawDataComplete(int result) { 551 void URLRequestJob::ReadRawDataComplete(int result) {
529 DCHECK(request_->status().is_io_pending()); 552 DCHECK(request_->status().is_io_pending());
553 DCHECK_NE(ERR_IO_PENDING, result);
530 554
531 // TODO(cbentzel): Remove ScopedTracker below once crbug.com/475755 is fixed. 555 // TODO(cbentzel): Remove ScopedTracker below once crbug.com/475755 is fixed.
532 tracked_objects::ScopedTracker tracking_profile( 556 tracked_objects::ScopedTracker tracking_profile(
533 FROM_HERE_WITH_EXPLICIT_FUNCTION( 557 FROM_HERE_WITH_EXPLICIT_FUNCTION(
534 "475755 URLRequestJob::RawReadCompleted")); 558 "475755 URLRequestJob::RawReadCompleted"));
535 559
536 // TODO(darin): Bug 1004233. Re-enable this test once all of the chrome 560 // TODO(darin): Bug 1004233. Re-enable this test once all of the chrome
537 // unit_tests have been fixed to not trip this. 561 // unit_tests have been fixed to not trip this.
538 #if 0 562 #if 0
539 DCHECK(!request_->status().is_io_pending()); 563 DCHECK(!request_->status().is_io_pending());
540 #endif 564 #endif
541 // The headers should be complete before reads complete 565 // The headers should be complete before reads complete
542 DCHECK(has_handled_response_); 566 DCHECK(has_handled_response_);
543 567
544 Error error; 568 GatherRawReadStats(result);
545 int bytes_read;
546 ConvertResultToError(result, &error, &bytes_read);
547 569
548 DCHECK_NE(ERR_IO_PENDING, error); 570 // Notify SourceStream.
571 DCHECK(!read_raw_callback_.is_null());
549 572
550 GatherRawReadStats(error, bytes_read); 573 base::ResetAndReturn(&read_raw_callback_).Run(result);
551
552 if (filter_.get() && error == OK) {
553 // |bytes_read| being 0 indicates an EOF was received. ReadFilteredData
554 // can incorrectly return ERR_IO_PENDING when 0 bytes are passed to it, so
555 // just don't call into the filter in that case.
556 int filter_bytes_read = 0;
557 if (bytes_read > 0) {
558 // Tell the filter that it has more data.
559 PushInputToFilter(bytes_read);
560
561 // Filter the data.
562 error = ReadFilteredData(&filter_bytes_read);
563 }
564
565 if (error == OK && !filter_bytes_read)
566 DoneReading();
567
568 DVLOG(1) << __func__ << "() \"" << request_->url().spec() << "\""
569 << " pre bytes read = " << bytes_read
570 << " pre total = " << prefilter_bytes_read_
571 << " post total = " << postfilter_bytes_read_;
572 bytes_read = filter_bytes_read;
573 } else {
574 DVLOG(1) << __func__ << "() \"" << request_->url().spec() << "\""
575 << " pre bytes read = " << bytes_read
576 << " pre total = " << prefilter_bytes_read_
577 << " post total = " << postfilter_bytes_read_;
578 }
579
580 // Synchronize the URLRequest state machine with the URLRequestJob state
581 // machine. If this read succeeded, either the request is at EOF and the
582 // URLRequest state machine goes to 'finished', or it is not and the
583 // URLRequest state machine goes to 'success'. If the read failed, the
584 // URLRequest state machine goes directly to 'finished'. If filtered data is
585 // pending, then there's nothing to do, since the status of the request is
586 // already pending.
587 //
588 // Update the URLRequest's status first, so that NotifyReadCompleted has an
589 // accurate view of the request.
590 if (error == OK && bytes_read > 0) {
591 SetStatus(URLRequestStatus());
592 } else if (error != ERR_IO_PENDING) {
593 NotifyDone(URLRequestStatus::FromError(error));
594 }
595
596 // NotifyReadCompleted should be called after SetStatus or NotifyDone updates
597 // the status.
598 if (error == OK)
599 request_->NotifyReadCompleted(bytes_read);
600
601 // |this| may be destroyed at this point. 574 // |this| may be destroyed at this point.
602 } 575 }
603 576
604 void URLRequestJob::NotifyStartError(const URLRequestStatus &status) { 577 void URLRequestJob::NotifyStartError(const URLRequestStatus &status) {
605 DCHECK(!has_handled_response_); 578 DCHECK(!has_handled_response_);
606 DCHECK(request_->status().is_io_pending()); 579 DCHECK(request_->status().is_io_pending());
607 580
608 has_handled_response_ = true; 581 has_handled_response_ = true;
609 // There may be relevant information in the response info even in the 582 // There may be relevant information in the response info even in the
610 // error case. 583 // error case.
(...skipping 29 matching lines...) Expand all
640 request_->set_status(status); 613 request_->set_status(status);
641 } 614 }
642 615
643 // If the request succeeded (And wasn't cancelled) and the response code was 616 // If the request succeeded (And wasn't cancelled) and the response code was
644 // 4xx or 5xx, record whether or not the main frame was blank. This is 617 // 4xx or 5xx, record whether or not the main frame was blank. This is
645 // intended to be a short-lived histogram, used to figure out how important 618 // intended to be a short-lived histogram, used to figure out how important
646 // fixing http://crbug.com/331745 is. 619 // fixing http://crbug.com/331745 is.
647 if (request_->status().is_success()) { 620 if (request_->status().is_success()) {
648 int response_code = GetResponseCode(); 621 int response_code = GetResponseCode();
649 if (400 <= response_code && response_code <= 599) { 622 if (400 <= response_code && response_code <= 599) {
650 bool page_has_content = (postfilter_bytes_read_ != 0); 623 bool page_has_content = (postfilter_bytes_read() != 0);
651 if (request_->load_flags() & net::LOAD_MAIN_FRAME) { 624 if (request_->load_flags() & net::LOAD_MAIN_FRAME) {
652 UMA_HISTOGRAM_BOOLEAN("Net.ErrorResponseHasContentMainFrame", 625 UMA_HISTOGRAM_BOOLEAN("Net.ErrorResponseHasContentMainFrame",
653 page_has_content); 626 page_has_content);
654 } else { 627 } else {
655 UMA_HISTOGRAM_BOOLEAN("Net.ErrorResponseHasContentNonMainFrame", 628 UMA_HISTOGRAM_BOOLEAN("Net.ErrorResponseHasContentNonMainFrame",
656 page_has_content); 629 page_has_content);
657 } 630 }
658 } 631 }
659 } 632 }
660 633
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 return 0; 679 return 0;
707 } 680 }
708 681
709 void URLRequestJob::DoneReading() { 682 void URLRequestJob::DoneReading() {
710 // Do nothing. 683 // Do nothing.
711 } 684 }
712 685
713 void URLRequestJob::DoneReadingRedirectResponse() { 686 void URLRequestJob::DoneReadingRedirectResponse() {
714 } 687 }
715 688
716 void URLRequestJob::PushInputToFilter(int bytes_read) { 689 std::unique_ptr<SourceStream> URLRequestJob::SetUpSourceStream() {
717 DCHECK(filter_); 690 return base::MakeUnique<URLRequestJobSourceStream>(this);
718 filter_->FlushStreamBuffer(bytes_read);
719 }
720
721 Error URLRequestJob::ReadFilteredData(int* bytes_read) {
722 DCHECK(filter_);
723 DCHECK(filtered_read_buffer_.get());
724 DCHECK_GT(filtered_read_buffer_len_, 0);
725 DCHECK_LT(filtered_read_buffer_len_, 1000000); // Sanity check.
726 DCHECK(!raw_read_buffer_);
727
728 *bytes_read = 0;
729 Error error = ERR_FAILED;
730
731 for (;;) {
732 if (is_done())
733 return OK;
734
735 if (!filter_needs_more_output_space_ && !filter_->stream_data_len()) {
736 // We don't have any raw data to work with, so read from the transaction.
737 int filtered_data_read;
738 error = ReadRawDataForFilter(&filtered_data_read);
739 // If ReadRawDataForFilter returned some data, fall through to the case
740 // below; otherwise, return early.
741 if (error != OK || filtered_data_read == 0)
742 return error;
743 filter_->FlushStreamBuffer(filtered_data_read);
744 }
745
746 if ((filter_->stream_data_len() || filter_needs_more_output_space_) &&
747 !is_done()) {
748 // Get filtered data.
749 int filtered_data_len = filtered_read_buffer_len_;
750 int output_buffer_size = filtered_data_len;
751 Filter::FilterStatus status =
752 filter_->ReadData(filtered_read_buffer_->data(), &filtered_data_len);
753
754 if (filter_needs_more_output_space_ && !filtered_data_len) {
755 // filter_needs_more_output_space_ was mistaken... there are no more
756 // bytes and we should have at least tried to fill up the filter's input
757 // buffer. Correct the state, and try again.
758 filter_needs_more_output_space_ = false;
759 continue;
760 }
761 filter_needs_more_output_space_ =
762 (filtered_data_len == output_buffer_size);
763
764 switch (status) {
765 case Filter::FILTER_DONE: {
766 filter_needs_more_output_space_ = false;
767 *bytes_read = filtered_data_len;
768 postfilter_bytes_read_ += filtered_data_len;
769 error = OK;
770 break;
771 }
772 case Filter::FILTER_NEED_MORE_DATA: {
773 // We have finished filtering all data currently in the buffer.
774 // There might be some space left in the output buffer. One can
775 // consider reading more data from the stream to feed the filter
776 // and filling up the output buffer. This leads to more complicated
777 // buffer management and data notification mechanisms.
778 // We can revisit this issue if there is a real perf need.
779 if (filtered_data_len > 0) {
780 *bytes_read = filtered_data_len;
781 postfilter_bytes_read_ += filtered_data_len;
782 error = OK;
783 } else {
784 // Read again since we haven't received enough data yet (e.g., we
785 // may not have a complete gzip header yet).
786 continue;
787 }
788 break;
789 }
790 case Filter::FILTER_OK: {
791 *bytes_read = filtered_data_len;
792 postfilter_bytes_read_ += filtered_data_len;
793 error = OK;
794 break;
795 }
796 case Filter::FILTER_ERROR: {
797 DVLOG(1) << __func__ << "() \"" << request_->url().spec() << "\""
798 << " Filter Error";
799 filter_needs_more_output_space_ = false;
800 error = ERR_CONTENT_DECODING_FAILED;
801 UMA_HISTOGRAM_ENUMERATION("Net.ContentDecodingFailed.FilterType",
802 filter_->type(), Filter::FILTER_TYPE_MAX);
803 break;
804 }
805 default: {
806 NOTREACHED();
807 filter_needs_more_output_space_ = false;
808 error = ERR_FAILED;
809 break;
810 }
811 }
812
813 // If logging all bytes is enabled, log the filtered bytes read.
814 if (error == OK && filtered_data_len > 0 &&
815 request()->net_log().IsCapturing()) {
816 request()->net_log().AddByteTransferEvent(
817 NetLog::TYPE_URL_REQUEST_JOB_FILTERED_BYTES_READ, filtered_data_len,
818 filtered_read_buffer_->data());
819 }
820 } else {
821 // we are done, or there is no data left.
822 error = OK;
823 }
824 break;
825 }
826
827 if (error == OK) {
828 // When we successfully finished a read, we no longer need to save the
829 // caller's buffers. Release our reference.
830 filtered_read_buffer_ = NULL;
831 filtered_read_buffer_len_ = 0;
832 }
833 return error;
834 }
835
836 void URLRequestJob::DestroyFilters() {
837 filter_.reset();
838 } 691 }
839 692
840 const URLRequestStatus URLRequestJob::GetStatus() { 693 const URLRequestStatus URLRequestJob::GetStatus() {
841 return request_->status(); 694 return request_->status();
842 } 695 }
843 696
844 void URLRequestJob::SetStatus(const URLRequestStatus &status) { 697 void URLRequestJob::SetStatus(const URLRequestStatus &status) {
845 // An error status should never be replaced by a non-error status by a 698 // An error status should never be replaced by a non-error status by a
846 // URLRequestJob. URLRequest has some retry paths, but it resets the status 699 // URLRequestJob. URLRequest has some retry paths, but it resets the status
847 // itself, if needed. 700 // itself, if needed.
848 DCHECK(request_->status().is_io_pending() || 701 DCHECK(request_->status().is_io_pending() ||
849 request_->status().is_success() || 702 request_->status().is_success() ||
850 (!status.is_success() && !status.is_io_pending())); 703 (!status.is_success() && !status.is_io_pending()));
851 request_->set_status(status); 704 request_->set_status(status);
852 } 705 }
853 706
854 void URLRequestJob::SetProxyServer(const HostPortPair& proxy_server) { 707 void URLRequestJob::SetProxyServer(const HostPortPair& proxy_server) {
855 request_->proxy_server_ = proxy_server; 708 request_->proxy_server_ = proxy_server;
856 } 709 }
857 710
858 Error URLRequestJob::ReadRawDataForFilter(int* bytes_read) { 711 void URLRequestJob::SourceStreamReadComplete(bool synchronous, int result) {
859 Error error = ERR_FAILED; 712 DCHECK_NE(ERR_IO_PENDING, result);
860 DCHECK(bytes_read);
861 DCHECK(filter_.get());
862 713
863 *bytes_read = 0; 714 if (result > 0 && request()->net_log().IsCapturing()) {
715 request()->net_log().AddByteTransferEvent(
716 NetLog::TYPE_URL_REQUEST_JOB_FILTERED_BYTES_READ, result,
717 pending_read_buffer_->data());
718 }
719 pending_read_buffer_ = nullptr;
864 720
865 // Get more pre-filtered data if needed. 721 if (result < 0) {
866 // TODO(mbelshe): is it possible that the filter needs *MORE* data 722 NotifyDone(URLRequestStatus::FromError(result));
867 // when there is some data already in the buffer? 723 return;
868 if (!filter_->stream_data_len() && !is_done()) {
869 IOBuffer* stream_buffer = filter_->stream_buffer();
870 int stream_buffer_size = filter_->stream_buffer_size();
871 error = ReadRawDataHelper(stream_buffer, stream_buffer_size, bytes_read);
872 } 724 }
873 return error; 725
726 if (result > 0) {
727 postfilter_bytes_read_ += result;
728 SetStatus(URLRequestStatus());
729 if (!synchronous)
730 request_->NotifyReadCompleted(result);
731 return;
732 }
733
734 // result == 0
735 DoneReading();
736 NotifyDone(URLRequestStatus());
737 if (!synchronous)
738 request_->NotifyReadCompleted(result);
874 } 739 }
875 740
876 Error URLRequestJob::ReadRawDataHelper(IOBuffer* buf, 741 int URLRequestJob::ReadRawDataHelper(IOBuffer* buf,
877 int buf_size, 742 int buf_size,
878 int* bytes_read) { 743 const CompletionCallback& callback) {
879 DCHECK(!raw_read_buffer_); 744 DCHECK(!raw_read_buffer_);
880 745
881 // Keep a pointer to the read buffer, so we have access to it in 746 // Keep a pointer to the read buffer, so URLRequestJob::GatherRawReadStats()
882 // GatherRawReadStats() in the event that the read completes asynchronously. 747 // has access to it to log stats.
883 raw_read_buffer_ = buf; 748 raw_read_buffer_ = buf;
884 Error error;
885 ConvertResultToError(ReadRawData(buf, buf_size), &error, bytes_read);
886 749
887 if (error != ERR_IO_PENDING) { 750 // TODO(xunjieli): Make ReadRawData take in a callback rather than requiring
751 // subclass to call ReadRawDataComplete upon asynchronous completion.
752 int result = ReadRawData(buf, buf_size);
753
754 if (result != ERR_IO_PENDING) {
888 // If the read completes synchronously, either success or failure, invoke 755 // If the read completes synchronously, either success or failure, invoke
889 // GatherRawReadStats so we can account for the completed read. 756 // GatherRawReadStats so we can account for the completed read.
890 GatherRawReadStats(error, *bytes_read); 757 GatherRawReadStats(result);
758 } else {
759 read_raw_callback_ = callback;
891 } 760 }
892 return error; 761 return result;
893 } 762 }
894 763
895 void URLRequestJob::FollowRedirect(const RedirectInfo& redirect_info) { 764 void URLRequestJob::FollowRedirect(const RedirectInfo& redirect_info) {
896 int rv = request_->Redirect(redirect_info); 765 int rv = request_->Redirect(redirect_info);
897 if (rv != OK) 766 if (rv != OK)
898 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); 767 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
899 } 768 }
900 769
901 void URLRequestJob::GatherRawReadStats(Error error, int bytes_read) { 770 void URLRequestJob::GatherRawReadStats(int bytes_read) {
902 DCHECK(raw_read_buffer_ || bytes_read == 0); 771 DCHECK(raw_read_buffer_ || bytes_read == 0);
903 DCHECK_NE(ERR_IO_PENDING, error); 772 DCHECK_NE(ERR_IO_PENDING, bytes_read);
904
905 if (error != OK) {
906 raw_read_buffer_ = nullptr;
907 return;
908 }
909 // If |filter_| is non-NULL, bytes will be logged after it is applied
910 // instead.
911 if (!filter_.get() && bytes_read > 0 && request()->net_log().IsCapturing()) {
912 request()->net_log().AddByteTransferEvent(
913 NetLog::TYPE_URL_REQUEST_JOB_BYTES_READ, bytes_read,
914 raw_read_buffer_->data());
915 }
916 773
917 if (bytes_read > 0) { 774 if (bytes_read > 0) {
775 if (request()->net_log().IsCapturing()) {
776 request()->net_log().AddByteTransferEvent(
777 NetLog::TYPE_URL_REQUEST_JOB_BYTES_READ, bytes_read,
778 raw_read_buffer_->data());
779 }
918 RecordBytesRead(bytes_read); 780 RecordBytesRead(bytes_read);
919 } 781 }
920 raw_read_buffer_ = nullptr; 782 raw_read_buffer_ = nullptr;
921 } 783 }
922 784
923 void URLRequestJob::RecordBytesRead(int bytes_read) { 785 void URLRequestJob::RecordBytesRead(int bytes_read) {
924 DCHECK_GT(bytes_read, 0); 786 DCHECK_GT(bytes_read, 0);
925 prefilter_bytes_read_ += bytes_read; 787 prefilter_bytes_read_ += base::checked_cast<size_t>(bytes_read);
926 788
927 // On first read, notify NetworkQualityEstimator that response headers have 789 // On first read, notify NetworkQualityEstimator that response headers have
928 // been received. 790 // been received.
929 // TODO(tbansal): Move this to url_request_http_job.cc. This may catch 791 // TODO(tbansal): Move this to url_request_http_job.cc. This may catch
930 // Service Worker jobs twice. 792 // Service Worker jobs twice.
931 // If prefilter_bytes_read_ is equal to bytes_read, it indicates this is the 793 // If prefilter_bytes_read_ is equal to bytes_read, it indicates this is the
932 // first raw read of the response body. This is used as the signal that 794 // first raw read of the response body. This is used as the signal that
933 // response headers have been received. 795 // response headers have been received.
934 if (request_->context()->network_quality_estimator() && 796 if (request_->context()->network_quality_estimator() &&
935 prefilter_bytes_read_ == bytes_read) { 797 prefilter_bytes_read() == bytes_read) {
936 request_->context()->network_quality_estimator()->NotifyHeadersReceived( 798 request_->context()->network_quality_estimator()->NotifyHeadersReceived(
937 *request_); 799 *request_);
938 } 800 }
939 801
940 if (!filter_.get()) 802 DVLOG(2) << __FUNCTION__ << "() "
941 postfilter_bytes_read_ += bytes_read; 803 << "\"" << request_->url().spec() << "\""
942 DVLOG(2) << __func__ << "() \"" << request_->url().spec() << "\""
943 << " pre bytes read = " << bytes_read 804 << " pre bytes read = " << bytes_read
944 << " pre total = " << prefilter_bytes_read_ 805 << " pre total = " << prefilter_bytes_read()
945 << " post total = " << postfilter_bytes_read_; 806 << " post total = " << postfilter_bytes_read();
946 UpdatePacketReadTimes(); // Facilitate stats recording if it is active. 807 UpdatePacketReadTimes(); // Facilitate stats recording if it is active.
947 808
948 // Notify observers if any additional network usage has occurred. Note that 809 // Notify observers if any additional network usage has occurred. Note that
949 // the number of received bytes over the network sent by this notification 810 // the number of received bytes over the network sent by this notification
950 // could be vastly different from |bytes_read|, such as when a large chunk of 811 // could be vastly different from |bytes_read|, such as when a large chunk of
951 // network bytes is received before multiple smaller raw reads are performed 812 // network bytes is received before multiple smaller raw reads are performed
952 // on it. 813 // on it.
953 MaybeNotifyNetworkBytes(); 814 MaybeNotifyNetworkBytes();
954 } 815 }
955 816
956 bool URLRequestJob::FilterHasData() {
957 return filter_.get() && filter_->stream_data_len();
958 }
959
960 void URLRequestJob::UpdatePacketReadTimes() { 817 void URLRequestJob::UpdatePacketReadTimes() {
961 } 818 }
962 819
963 RedirectInfo URLRequestJob::ComputeRedirectInfo(const GURL& location, 820 RedirectInfo URLRequestJob::ComputeRedirectInfo(const GURL& location,
964 int http_status_code) { 821 int http_status_code) {
965 const GURL& url = request_->url(); 822 const GURL& url = request_->url();
966 823
967 RedirectInfo redirect_info; 824 RedirectInfo redirect_info;
968 825
969 redirect_info.status_code = http_status_code; 826 redirect_info.status_code = http_status_code;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 int64_t total_sent_bytes = GetTotalSentBytes(); 893 int64_t total_sent_bytes = GetTotalSentBytes();
1037 DCHECK_GE(total_sent_bytes, last_notified_total_sent_bytes_); 894 DCHECK_GE(total_sent_bytes, last_notified_total_sent_bytes_);
1038 if (total_sent_bytes > last_notified_total_sent_bytes_) { 895 if (total_sent_bytes > last_notified_total_sent_bytes_) {
1039 network_delegate_->NotifyNetworkBytesSent( 896 network_delegate_->NotifyNetworkBytesSent(
1040 request_, total_sent_bytes - last_notified_total_sent_bytes_); 897 request_, total_sent_bytes - last_notified_total_sent_bytes_);
1041 } 898 }
1042 last_notified_total_sent_bytes_ = total_sent_bytes; 899 last_notified_total_sent_bytes_ = total_sent_bytes;
1043 } 900 }
1044 901
1045 } // namespace net 902 } // namespace net
OLDNEW
« no previous file with comments | « net/url_request/url_request_job.h ('k') | net/url_request/url_request_job_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698