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

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: add filter_source_stream_unittest.cc and address other comments 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
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 // SourceStreams own the previous SourceStream in the chain, but the ultimate
Randy Smith (Not in Mondays) 2016/08/09 20:28:31 nit, suggested rephrasing: "Each SourceStream owns
xunjieli 2016/08/15 15:19:08 Done.
120 // source is URLRequestJob, which has other ownership semantics, so this class
121 // is a proxy for URLRequestJob that is owned by the first filter (in dataflow
Randy Smith (Not in Mondays) 2016/08/09 20:28:30 nit, suggestion: " ... first stream (in ..."?
xunjieli 2016/08/15 15:19:08 Done.
122 // 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 private:
141 URLRequestJob* const job_;
Randy Smith (Not in Mondays) 2016/08/09 20:28:31 nit: Comment on why it's safe to keep a raw pointe
xunjieli 2016/08/15 15:19:08 Done.
142
143 DISALLOW_COPY_AND_ASSIGN(URLRequestJobSourceStream);
144 };
145
118 URLRequestJob::URLRequestJob(URLRequest* request, 146 URLRequestJob::URLRequestJob(URLRequest* request,
119 NetworkDelegate* network_delegate) 147 NetworkDelegate* network_delegate)
120 : request_(request), 148 : request_(request),
121 done_(false), 149 done_(false),
122 prefilter_bytes_read_(0), 150 prefilter_bytes_read_(0),
123 postfilter_bytes_read_(0), 151 postfilter_bytes_read_(0),
124 filter_needs_more_output_space_(false),
125 filtered_read_buffer_len_(0),
126 has_handled_response_(false), 152 has_handled_response_(false),
127 expected_content_size_(-1), 153 expected_content_size_(-1),
128 network_delegate_(network_delegate), 154 network_delegate_(network_delegate),
129 last_notified_total_received_bytes_(0), 155 last_notified_total_received_bytes_(0),
130 last_notified_total_sent_bytes_(0), 156 last_notified_total_sent_bytes_(0),
131 weak_factory_(this) { 157 weak_factory_(this) {
132 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); 158 base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
133 if (power_monitor) 159 if (power_monitor)
134 power_monitor->AddObserver(this); 160 power_monitor->AddObserver(this);
135 } 161 }
(...skipping 20 matching lines...) Expand all
156 // Kill(). 182 // Kill().
157 // TODO(mmenke): The URLRequest is currently deleted before this method 183 // TODO(mmenke): The URLRequest is currently deleted before this method
158 // invokes its async callback whenever this is called by the URLRequest. 184 // invokes its async callback whenever this is called by the URLRequest.
159 // Try to simplify how cancellation works. 185 // Try to simplify how cancellation works.
160 NotifyCanceled(); 186 NotifyCanceled();
161 } 187 }
162 188
163 // This function calls ReadRawData to get stream data. If a filter exists, it 189 // 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 190 // passes the data to the attached filter. It then returns the output from
165 // filter back to the caller. 191 // filter back to the caller.
192 // This method passes reads down the filter chain, where they eventually end up
193 // at URLRequestJobSourceStream::Read, which calls back into
194 // URLRequestJob::ReadRawData.
166 bool URLRequestJob::Read(IOBuffer* buf, int buf_size, int *bytes_read) { 195 bool URLRequestJob::Read(IOBuffer* buf, int buf_size, int *bytes_read) {
167 DCHECK_LT(buf_size, 1000000); // Sanity check. 196 DCHECK_LT(buf_size, 1000000); // Sanity check.
168 DCHECK(buf); 197 DCHECK(buf);
169 DCHECK(bytes_read); 198 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; 199 *bytes_read = 0;
175 200
176 // Skip Filter if not present. 201 pending_read_buffer_ = buf;
177 if (!filter_) { 202 int result = source_stream_->Read(
178 error = ReadRawDataHelper(buf, buf_size, bytes_read); 203 buf, buf_size, base::Bind(&URLRequestJob::SourceReadComplete,
179 } else { 204 weak_factory_.GetWeakPtr(), false));
180 // Save the caller's buffers while we do IO 205 if (result > 0)
181 // in the filter's buffers. 206 *bytes_read = result;
Randy Smith (Not in Mondays) 2016/08/09 20:28:31 nitty nit, suggestion: I'd find the grouping in th
xunjieli 2016/08/15 15:19:08 Done.
182 filtered_read_buffer_ = buf;
183 filtered_read_buffer_len_ = buf_size;
184 207
185 error = ReadFilteredData(bytes_read); 208 if (result == ERR_IO_PENDING) {
186 209 SetStatus(URLRequestStatus::FromError(ERR_IO_PENDING));
187 // Synchronous EOF from the filter. 210 return false;
188 if (error == OK && *bytes_read == 0)
189 DoneReading();
190 } 211 }
191 212
192 if (error == OK) { 213 SourceReadComplete(true, result);
193 // If URLRequestJob read zero bytes, the job is at EOF. 214 return result >= OK;
194 if (*bytes_read == 0) 215 }
195 NotifyDone(URLRequestStatus()); 216
196 } else if (error == ERR_IO_PENDING) { 217 void URLRequestJob::SourceReadComplete(bool synchronous, int result) {
Randy Smith (Not in Mondays) 2016/08/09 20:28:30 nit, suggestion: Change name to "StreamReadComplet
xunjieli 2016/08/15 15:19:08 Done.
197 SetStatus(URLRequestStatus::FromError(ERR_IO_PENDING)); 218 DCHECK_NE(ERR_IO_PENDING, result);
198 } else { 219
199 NotifyDone(URLRequestStatus::FromError(error)); 220 if (result > 0 && request()->net_log().IsCapturing()) {
200 *bytes_read = -1; 221 request()->net_log().AddByteTransferEvent(
222 NetLog::TYPE_URL_REQUEST_JOB_FILTERED_BYTES_READ, result,
223 pending_read_buffer_->data());
201 } 224 }
202 return error == OK; 225 pending_read_buffer_ = nullptr;
226
227 if (result < 0) {
228 NotifyDone(URLRequestStatus::FromError(result));
229 return;
230 }
231
232 if (result > 0) {
233 postfilter_bytes_read_ += result;
234 SetStatus(URLRequestStatus());
235 if (!synchronous)
236 request_->NotifyReadCompleted(result);
237 return;
238 }
239
240 // result == 0
241 DoneReading();
242 NotifyDone(URLRequestStatus());
243 if (!synchronous)
244 request_->NotifyReadCompleted(result);
203 } 245 }
204 246
205 void URLRequestJob::StopCaching() { 247 void URLRequestJob::StopCaching() {
206 // Nothing to do here. 248 // Nothing to do here.
207 } 249 }
208 250
209 bool URLRequestJob::GetFullRequestHeaders(HttpRequestHeaders* headers) const { 251 bool URLRequestJob::GetFullRequestHeaders(HttpRequestHeaders* headers) const {
210 // Most job types don't send request headers. 252 // Most job types don't send request headers.
211 return false; 253 return false;
212 } 254 }
(...skipping 26 matching lines...) Expand all
239 } 281 }
240 282
241 bool URLRequestJob::GetRemoteEndpoint(IPEndPoint* endpoint) const { 283 bool URLRequestJob::GetRemoteEndpoint(IPEndPoint* endpoint) const {
242 return false; 284 return false;
243 } 285 }
244 286
245 void URLRequestJob::PopulateNetErrorDetails(NetErrorDetails* details) const { 287 void URLRequestJob::PopulateNetErrorDetails(NetErrorDetails* details) const {
246 return; 288 return;
247 } 289 }
248 290
249 std::unique_ptr<Filter> URLRequestJob::SetupFilter() const {
250 return nullptr;
251 }
252
253 bool URLRequestJob::IsRedirectResponse(GURL* location, 291 bool URLRequestJob::IsRedirectResponse(GURL* location,
254 int* http_status_code) { 292 int* http_status_code) {
255 // For non-HTTP jobs, headers will be null. 293 // For non-HTTP jobs, headers will be null.
256 HttpResponseHeaders* headers = request_->response_headers(); 294 HttpResponseHeaders* headers = request_->response_headers();
257 if (!headers) 295 if (!headers)
258 return false; 296 return false;
259 297
260 std::string value; 298 std::string value;
261 if (!headers->IsRedirect(&value)) 299 if (!headers->IsRedirect(&value))
262 return false; 300 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 527 // Need to check for a NULL auth_info because the server may have failed
490 // to send a challenge with the 401 response. 528 // to send a challenge with the 401 response.
491 if (auth_info.get()) { 529 if (auth_info.get()) {
492 request_->NotifyAuthRequired(auth_info.get()); 530 request_->NotifyAuthRequired(auth_info.get());
493 // Wait for SetAuth or CancelAuth to be called. 531 // Wait for SetAuth or CancelAuth to be called.
494 return; 532 return;
495 } 533 }
496 } 534 }
497 535
498 has_handled_response_ = true; 536 has_handled_response_ = true;
499 if (request_->status().is_success()) 537 if (request_->status().is_success()) {
500 filter_ = SetupFilter(); 538 DCHECK(!source_stream_);
539 source_stream_ = SetUpSourceStream();
501 540
502 if (!filter_.get()) { 541 if (source_stream_ == nullptr) {
503 std::string content_length; 542 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
504 request_->GetResponseHeaderByName("content-length", &content_length); 543 ERR_CONTENT_DECODING_INIT_FAILED));
505 if (!content_length.empty()) 544 return;
506 base::StringToInt64(content_length, &expected_content_size_); 545 }
507 } else { 546
508 request_->net_log().AddEvent( 547 if (source_stream_->type() == SourceStream::TYPE_NONE) {
509 NetLog::TYPE_URL_REQUEST_FILTERS_SET, 548 std::string content_length;
510 base::Bind(&FiltersSetCallback, base::Unretained(filter_.get()))); 549 request_->GetResponseHeaderByName("content-length", &content_length);
550 if (!content_length.empty())
551 base::StringToInt64(content_length, &expected_content_size_);
552 } else {
553 request_->net_log().AddEvent(
554 NetLog::TYPE_URL_REQUEST_FILTERS_SET,
555 base::Bind(&SourceStreamSetCallback,
556 base::Unretained(source_stream_.get())));
557 }
511 } 558 }
512 559
513 request_->NotifyResponseStarted(); 560 request_->NotifyResponseStarted();
514 561
515 // |this| may be destroyed at this point. 562 // |this| may be destroyed at this point.
516 } 563 }
517 564
518 void URLRequestJob::ConvertResultToError(int result, Error* error, int* count) { 565 void URLRequestJob::ConvertResultToError(int result, Error* error, int* count) {
519 if (result >= 0) { 566 if (result >= 0) {
520 *error = OK; 567 *error = OK;
521 *count = result; 568 *count = result;
522 } else { 569 } else {
523 *error = static_cast<Error>(result); 570 *error = static_cast<Error>(result);
524 *count = 0; 571 *count = 0;
525 } 572 }
526 } 573 }
527 574
528 void URLRequestJob::ReadRawDataComplete(int result) { 575 void URLRequestJob::ReadRawDataComplete(int result) {
Randy Smith (Not in Mondays) 2016/08/09 20:28:30 nit, suggestion: Name this function in parallel fa
xunjieli 2016/08/15 15:19:08 Acknowledged. Let's do it in a follow-up? This one
Randy Smith (Not in Mondays) 2016/08/22 18:12:31 Sure, that's fine. Let's keep a list of followup
529 DCHECK(request_->status().is_io_pending()); 576 DCHECK(request_->status().is_io_pending());
577 DCHECK_NE(ERR_IO_PENDING, result);
530 578
531 // TODO(cbentzel): Remove ScopedTracker below once crbug.com/475755 is fixed. 579 // TODO(cbentzel): Remove ScopedTracker below once crbug.com/475755 is fixed.
532 tracked_objects::ScopedTracker tracking_profile( 580 tracked_objects::ScopedTracker tracking_profile(
533 FROM_HERE_WITH_EXPLICIT_FUNCTION( 581 FROM_HERE_WITH_EXPLICIT_FUNCTION(
534 "475755 URLRequestJob::RawReadCompleted")); 582 "475755 URLRequestJob::RawReadCompleted"));
535 583
536 // TODO(darin): Bug 1004233. Re-enable this test once all of the chrome 584 // TODO(darin): Bug 1004233. Re-enable this test once all of the chrome
537 // unit_tests have been fixed to not trip this. 585 // unit_tests have been fixed to not trip this.
538 #if 0 586 #if 0
539 DCHECK(!request_->status().is_io_pending()); 587 DCHECK(!request_->status().is_io_pending());
540 #endif 588 #endif
541 // The headers should be complete before reads complete 589 // The headers should be complete before reads complete
542 DCHECK(has_handled_response_); 590 DCHECK(has_handled_response_);
543 591
544 Error error; 592 GatherRawReadStats(result);
545 int bytes_read;
546 ConvertResultToError(result, &error, &bytes_read);
547 593
548 DCHECK_NE(ERR_IO_PENDING, error); 594 // Notify SourceStream.
595 DCHECK(!read_raw_callback_.is_null());
549 596
550 GatherRawReadStats(error, bytes_read); 597 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. 598 // |this| may be destroyed at this point.
602 } 599 }
603 600
604 void URLRequestJob::NotifyStartError(const URLRequestStatus &status) { 601 void URLRequestJob::NotifyStartError(const URLRequestStatus &status) {
605 DCHECK(!has_handled_response_); 602 DCHECK(!has_handled_response_);
606 DCHECK(request_->status().is_io_pending()); 603 DCHECK(request_->status().is_io_pending());
607 604
608 has_handled_response_ = true; 605 has_handled_response_ = true;
609 // There may be relevant information in the response info even in the 606 // There may be relevant information in the response info even in the
610 // error case. 607 // error case.
(...skipping 29 matching lines...) Expand all
640 request_->set_status(status); 637 request_->set_status(status);
641 } 638 }
642 639
643 // If the request succeeded (And wasn't cancelled) and the response code was 640 // 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 641 // 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 642 // intended to be a short-lived histogram, used to figure out how important
646 // fixing http://crbug.com/331745 is. 643 // fixing http://crbug.com/331745 is.
647 if (request_->status().is_success()) { 644 if (request_->status().is_success()) {
648 int response_code = GetResponseCode(); 645 int response_code = GetResponseCode();
649 if (400 <= response_code && response_code <= 599) { 646 if (400 <= response_code && response_code <= 599) {
650 bool page_has_content = (postfilter_bytes_read_ != 0); 647 bool page_has_content = (postfilter_bytes_read() != 0);
651 if (request_->load_flags() & net::LOAD_MAIN_FRAME) { 648 if (request_->load_flags() & net::LOAD_MAIN_FRAME) {
652 UMA_HISTOGRAM_BOOLEAN("Net.ErrorResponseHasContentMainFrame", 649 UMA_HISTOGRAM_BOOLEAN("Net.ErrorResponseHasContentMainFrame",
653 page_has_content); 650 page_has_content);
654 } else { 651 } else {
655 UMA_HISTOGRAM_BOOLEAN("Net.ErrorResponseHasContentNonMainFrame", 652 UMA_HISTOGRAM_BOOLEAN("Net.ErrorResponseHasContentNonMainFrame",
656 page_has_content); 653 page_has_content);
657 } 654 }
658 } 655 }
659 } 656 }
660 657
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 return 0; 703 return 0;
707 } 704 }
708 705
709 void URLRequestJob::DoneReading() { 706 void URLRequestJob::DoneReading() {
710 // Do nothing. 707 // Do nothing.
711 } 708 }
712 709
713 void URLRequestJob::DoneReadingRedirectResponse() { 710 void URLRequestJob::DoneReadingRedirectResponse() {
714 } 711 }
715 712
716 void URLRequestJob::PushInputToFilter(int bytes_read) { 713 std::unique_ptr<SourceStream> URLRequestJob::SetUpSourceStream() {
717 DCHECK(filter_); 714 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 } 715 }
839 716
840 const URLRequestStatus URLRequestJob::GetStatus() { 717 const URLRequestStatus URLRequestJob::GetStatus() {
841 return request_->status(); 718 return request_->status();
842 } 719 }
843 720
844 void URLRequestJob::SetStatus(const URLRequestStatus &status) { 721 void URLRequestJob::SetStatus(const URLRequestStatus &status) {
845 // An error status should never be replaced by a non-error status by a 722 // 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 723 // URLRequestJob. URLRequest has some retry paths, but it resets the status
847 // itself, if needed. 724 // itself, if needed.
848 DCHECK(request_->status().is_io_pending() || 725 DCHECK(request_->status().is_io_pending() ||
849 request_->status().is_success() || 726 request_->status().is_success() ||
850 (!status.is_success() && !status.is_io_pending())); 727 (!status.is_success() && !status.is_io_pending()));
851 request_->set_status(status); 728 request_->set_status(status);
852 } 729 }
853 730
854 void URLRequestJob::SetProxyServer(const HostPortPair& proxy_server) { 731 void URLRequestJob::SetProxyServer(const HostPortPair& proxy_server) {
855 request_->proxy_server_ = proxy_server; 732 request_->proxy_server_ = proxy_server;
856 } 733 }
857 734
858 Error URLRequestJob::ReadRawDataForFilter(int* bytes_read) { 735 int URLRequestJob::ReadRawDataHelper(IOBuffer* buf,
859 Error error = ERR_FAILED; 736 int buf_size,
860 DCHECK(bytes_read); 737 const CompletionCallback& callback) {
861 DCHECK(filter_.get());
862
863 *bytes_read = 0;
864
865 // Get more pre-filtered data if needed.
866 // TODO(mbelshe): is it possible that the filter needs *MORE* data
867 // when there is some data already in the buffer?
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 }
873 return error;
874 }
875
876 Error URLRequestJob::ReadRawDataHelper(IOBuffer* buf,
877 int buf_size,
878 int* bytes_read) {
879 DCHECK(!raw_read_buffer_); 738 DCHECK(!raw_read_buffer_);
880 739
881 // Keep a pointer to the read buffer, so we have access to it in 740 // Keep a pointer to the read buffer, so URLRequestJob::GatherRawReadStats()
882 // GatherRawReadStats() in the event that the read completes asynchronously. 741 // has access to it to log stats.
883 raw_read_buffer_ = buf; 742 raw_read_buffer_ = buf;
884 Error error; 743 int result = ReadRawData(buf, buf_size);
885 ConvertResultToError(ReadRawData(buf, buf_size), &error, bytes_read);
886 744
887 if (error != ERR_IO_PENDING) { 745 if (result != ERR_IO_PENDING) {
888 // If the read completes synchronously, either success or failure, invoke 746 // If the read completes synchronously, either success or failure, invoke
889 // GatherRawReadStats so we can account for the completed read. 747 // GatherRawReadStats so we can account for the completed read.
890 GatherRawReadStats(error, *bytes_read); 748 GatherRawReadStats(result);
Randy Smith (Not in Mondays) 2016/08/09 20:28:31 Would you be willing to put in a TODO() to cleanup
xunjieli 2016/08/15 15:19:08 Done.
749 } else {
750 read_raw_callback_ = callback;
891 } 751 }
892 return error; 752 return result;
893 } 753 }
894 754
895 void URLRequestJob::FollowRedirect(const RedirectInfo& redirect_info) { 755 void URLRequestJob::FollowRedirect(const RedirectInfo& redirect_info) {
896 int rv = request_->Redirect(redirect_info); 756 int rv = request_->Redirect(redirect_info);
897 if (rv != OK) 757 if (rv != OK)
898 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); 758 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
899 } 759 }
900 760
901 void URLRequestJob::GatherRawReadStats(Error error, int bytes_read) { 761 void URLRequestJob::GatherRawReadStats(int bytes_read) {
Randy Smith (Not in Mondays) 2016/08/09 20:28:30 nit, suggestion: This routine is a bit misleadingl
xunjieli 2016/08/15 15:19:08 Acknowledged. ReadRawDataComplete is used by all s
902 DCHECK(raw_read_buffer_ || bytes_read == 0); 762 DCHECK(raw_read_buffer_ || bytes_read == 0);
903 DCHECK_NE(ERR_IO_PENDING, error); 763 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 764
917 if (bytes_read > 0) { 765 if (bytes_read > 0) {
766 if (request()->net_log().IsCapturing()) {
767 request()->net_log().AddByteTransferEvent(
768 NetLog::TYPE_URL_REQUEST_JOB_BYTES_READ, bytes_read,
769 raw_read_buffer_->data());
770 }
918 RecordBytesRead(bytes_read); 771 RecordBytesRead(bytes_read);
919 } 772 }
920 raw_read_buffer_ = nullptr; 773 raw_read_buffer_ = nullptr;
921 } 774 }
922 775
923 void URLRequestJob::RecordBytesRead(int bytes_read) { 776 void URLRequestJob::RecordBytesRead(int bytes_read) {
924 DCHECK_GT(bytes_read, 0); 777 DCHECK_GT(bytes_read, 0);
925 prefilter_bytes_read_ += bytes_read; 778 prefilter_bytes_read_ += base::checked_cast<size_t>(bytes_read);
926 779
927 // On first read, notify NetworkQualityEstimator that response headers have 780 // On first read, notify NetworkQualityEstimator that response headers have
928 // been received. 781 // been received.
929 // TODO(tbansal): Move this to url_request_http_job.cc. This may catch 782 // TODO(tbansal): Move this to url_request_http_job.cc. This may catch
930 // Service Worker jobs twice. 783 // Service Worker jobs twice.
931 // If prefilter_bytes_read_ is equal to bytes_read, it indicates this is the 784 // 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 785 // first raw read of the response body. This is used as the signal that
933 // response headers have been received. 786 // response headers have been received.
934 if (request_->context()->network_quality_estimator() && 787 if (request_->context()->network_quality_estimator() &&
935 prefilter_bytes_read_ == bytes_read) { 788 prefilter_bytes_read() == bytes_read) {
936 request_->context()->network_quality_estimator()->NotifyHeadersReceived( 789 request_->context()->network_quality_estimator()->NotifyHeadersReceived(
937 *request_); 790 *request_);
938 } 791 }
939 792
940 if (!filter_.get()) 793 DVLOG(2) << __FUNCTION__ << "() "
941 postfilter_bytes_read_ += bytes_read; 794 << "\"" << request_->url().spec() << "\""
942 DVLOG(2) << __func__ << "() \"" << request_->url().spec() << "\""
943 << " pre bytes read = " << bytes_read 795 << " pre bytes read = " << bytes_read
944 << " pre total = " << prefilter_bytes_read_ 796 << " pre total = " << prefilter_bytes_read()
945 << " post total = " << postfilter_bytes_read_; 797 << " post total = " << postfilter_bytes_read();
946 UpdatePacketReadTimes(); // Facilitate stats recording if it is active. 798 UpdatePacketReadTimes(); // Facilitate stats recording if it is active.
947 799
948 // Notify observers if any additional network usage has occurred. Note that 800 // Notify observers if any additional network usage has occurred. Note that
949 // the number of received bytes over the network sent by this notification 801 // 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 802 // 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 803 // network bytes is received before multiple smaller raw reads are performed
952 // on it. 804 // on it.
953 MaybeNotifyNetworkBytes(); 805 MaybeNotifyNetworkBytes();
954 } 806 }
955 807
956 bool URLRequestJob::FilterHasData() {
957 return filter_.get() && filter_->stream_data_len();
958 }
959
960 void URLRequestJob::UpdatePacketReadTimes() { 808 void URLRequestJob::UpdatePacketReadTimes() {
961 } 809 }
962 810
963 RedirectInfo URLRequestJob::ComputeRedirectInfo(const GURL& location, 811 RedirectInfo URLRequestJob::ComputeRedirectInfo(const GURL& location,
964 int http_status_code) { 812 int http_status_code) {
965 const GURL& url = request_->url(); 813 const GURL& url = request_->url();
966 814
967 RedirectInfo redirect_info; 815 RedirectInfo redirect_info;
968 816
969 redirect_info.status_code = http_status_code; 817 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(); 884 int64_t total_sent_bytes = GetTotalSentBytes();
1037 DCHECK_GE(total_sent_bytes, last_notified_total_sent_bytes_); 885 DCHECK_GE(total_sent_bytes, last_notified_total_sent_bytes_);
1038 if (total_sent_bytes > last_notified_total_sent_bytes_) { 886 if (total_sent_bytes > last_notified_total_sent_bytes_) {
1039 network_delegate_->NotifyNetworkBytesSent( 887 network_delegate_->NotifyNetworkBytesSent(
1040 request_, total_sent_bytes - last_notified_total_sent_bytes_); 888 request_, total_sent_bytes - last_notified_total_sent_bytes_);
1041 } 889 }
1042 last_notified_total_sent_bytes_ = total_sent_bytes; 890 last_notified_total_sent_bytes_ = total_sent_bytes;
1043 } 891 }
1044 892
1045 } // namespace net 893 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698