| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "base/message_loop.h" | 7 #include "base/message_loop.h" |
| 8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 observed_packet_count_(0) { | 46 observed_packet_count_(0) { |
| 47 load_flags_ = request_->load_flags(); | 47 load_flags_ = request_->load_flags(); |
| 48 is_profiling_ = request->enable_profiling(); | 48 is_profiling_ = request->enable_profiling(); |
| 49 if (is_profiling()) { | 49 if (is_profiling()) { |
| 50 metrics_.reset(new URLRequestJobMetrics()); | 50 metrics_.reset(new URLRequestJobMetrics()); |
| 51 metrics_->start_time_ = TimeTicks::Now(); | 51 metrics_->start_time_ = TimeTicks::Now(); |
| 52 } | 52 } |
| 53 g_url_request_job_tracker.AddNewJob(this); | 53 g_url_request_job_tracker.AddNewJob(this); |
| 54 } | 54 } |
| 55 | 55 |
| 56 URLRequestJob::~URLRequestJob() { | |
| 57 g_url_request_job_tracker.RemoveJob(this); | |
| 58 } | |
| 59 | |
| 60 void URLRequestJob::SetUpload(net::UploadData* upload) { | 56 void URLRequestJob::SetUpload(net::UploadData* upload) { |
| 61 } | 57 } |
| 62 | 58 |
| 63 void URLRequestJob::SetExtraRequestHeaders( | 59 void URLRequestJob::SetExtraRequestHeaders( |
| 64 const net::HttpRequestHeaders& headers) { | 60 const net::HttpRequestHeaders& headers) { |
| 65 } | 61 } |
| 66 | 62 |
| 67 void URLRequestJob::Kill() { | 63 void URLRequestJob::Kill() { |
| 68 // Make sure the request is notified that we are done. We assume that the | 64 // Make sure the request is notified that we are done. We assume that the |
| 69 // request took care of setting its error status before calling Kill. | 65 // request took care of setting its error status before calling Kill. |
| 70 if (request_) | 66 if (request_) |
| 71 NotifyCanceled(); | 67 NotifyCanceled(); |
| 72 } | 68 } |
| 73 | 69 |
| 74 void URLRequestJob::DetachRequest() { | 70 void URLRequestJob::DetachRequest() { |
| 75 request_ = NULL; | 71 request_ = NULL; |
| 76 } | 72 } |
| 77 | 73 |
| 74 // This function calls ReadData to get stream data. If a filter exists, passes |
| 75 // the data to the attached filter. Then returns the output from filter back to |
| 76 // the caller. |
| 77 bool URLRequestJob::Read(net::IOBuffer* buf, int buf_size, int *bytes_read) { |
| 78 bool rv = false; |
| 79 |
| 80 DCHECK_LT(buf_size, 1000000); // sanity check |
| 81 DCHECK(buf); |
| 82 DCHECK(bytes_read); |
| 83 DCHECK(filtered_read_buffer_ == NULL); |
| 84 DCHECK_EQ(0, filtered_read_buffer_len_); |
| 85 |
| 86 *bytes_read = 0; |
| 87 |
| 88 // Skip Filter if not present |
| 89 if (!filter_.get()) { |
| 90 rv = ReadRawDataHelper(buf, buf_size, bytes_read); |
| 91 } else { |
| 92 // Save the caller's buffers while we do IO |
| 93 // in the filter's buffers. |
| 94 filtered_read_buffer_ = buf; |
| 95 filtered_read_buffer_len_ = buf_size; |
| 96 |
| 97 if (ReadFilteredData(bytes_read)) { |
| 98 rv = true; // we have data to return |
| 99 } else { |
| 100 rv = false; // error, or a new IO is pending |
| 101 } |
| 102 } |
| 103 if (rv && *bytes_read == 0) |
| 104 NotifyDone(URLRequestStatus()); |
| 105 return rv; |
| 106 } |
| 107 |
| 108 void URLRequestJob::StopCaching() { |
| 109 // Nothing to do here. |
| 110 } |
| 111 |
| 112 net::LoadState URLRequestJob::GetLoadState() const { |
| 113 return net::LOAD_STATE_IDLE; |
| 114 } |
| 115 |
| 116 uint64 URLRequestJob::GetUploadProgress() const { |
| 117 return 0; |
| 118 } |
| 119 |
| 120 bool URLRequestJob::GetCharset(std::string* charset) { |
| 121 return false; |
| 122 } |
| 123 |
| 124 void URLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { |
| 125 } |
| 126 |
| 127 bool URLRequestJob::GetResponseCookies(std::vector<std::string>* cookies) { |
| 128 return false; |
| 129 } |
| 130 |
| 131 bool URLRequestJob::GetContentEncodings( |
| 132 std::vector<Filter::FilterType>* encoding_types) { |
| 133 return false; |
| 134 } |
| 135 |
| 78 void URLRequestJob::SetupFilter() { | 136 void URLRequestJob::SetupFilter() { |
| 79 std::vector<Filter::FilterType> encoding_types; | 137 std::vector<Filter::FilterType> encoding_types; |
| 80 if (GetContentEncodings(&encoding_types)) { | 138 if (GetContentEncodings(&encoding_types)) { |
| 81 filter_.reset(Filter::Factory(encoding_types, *this)); | 139 filter_.reset(Filter::Factory(encoding_types, *this)); |
| 82 } | 140 } |
| 83 } | 141 } |
| 84 | 142 |
| 85 bool URLRequestJob::IsRedirectResponse(GURL* location, | 143 bool URLRequestJob::IsRedirectResponse(GURL* location, |
| 86 int* http_status_code) { | 144 int* http_status_code) { |
| 87 // For non-HTTP jobs, headers will be null. | 145 // For non-HTTP jobs, headers will be null. |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 | 209 |
| 152 GURL redirect_url = deferred_redirect_url_; | 210 GURL redirect_url = deferred_redirect_url_; |
| 153 int redirect_status_code = deferred_redirect_status_code_; | 211 int redirect_status_code = deferred_redirect_status_code_; |
| 154 | 212 |
| 155 deferred_redirect_url_ = GURL(); | 213 deferred_redirect_url_ = GURL(); |
| 156 deferred_redirect_status_code_ = -1; | 214 deferred_redirect_status_code_ = -1; |
| 157 | 215 |
| 158 FollowRedirect(redirect_url, redirect_status_code); | 216 FollowRedirect(redirect_url, redirect_status_code); |
| 159 } | 217 } |
| 160 | 218 |
| 161 int64 URLRequestJob::GetByteReadCount() const { | 219 URLRequestJobMetrics* URLRequestJob::RetrieveMetrics() { |
| 162 return filter_input_byte_count_; | 220 if (is_profiling()) |
| 221 return metrics_.release(); |
| 222 else |
| 223 return NULL; |
| 163 } | 224 } |
| 164 | 225 |
| 165 bool URLRequestJob::GetMimeType(std::string* mime_type) const { | 226 bool URLRequestJob::GetMimeType(std::string* mime_type) const { |
| 166 return false; | 227 return false; |
| 167 } | 228 } |
| 168 | 229 |
| 169 bool URLRequestJob::GetURL(GURL* gurl) const { | 230 bool URLRequestJob::GetURL(GURL* gurl) const { |
| 170 if (!request_) | 231 if (!request_) |
| 171 return false; | 232 return false; |
| 172 *gurl = request_->url(); | 233 *gurl = request_->url(); |
| 173 return true; | 234 return true; |
| 174 } | 235 } |
| 175 | 236 |
| 176 base::Time URLRequestJob::GetRequestTime() const { | 237 base::Time URLRequestJob::GetRequestTime() const { |
| 177 if (!request_) | 238 if (!request_) |
| 178 return base::Time(); | 239 return base::Time(); |
| 179 return request_->request_time(); | 240 return request_->request_time(); |
| 180 }; | 241 } |
| 242 |
| 243 bool URLRequestJob::IsDownload() const { |
| 244 return (load_flags_ & net::LOAD_IS_DOWNLOAD) != 0; |
| 245 } |
| 246 |
| 247 bool URLRequestJob::IsSdchResponse() const { |
| 248 return false; |
| 249 } |
| 181 | 250 |
| 182 bool URLRequestJob::IsCachedContent() const { | 251 bool URLRequestJob::IsCachedContent() const { |
| 183 return false; | 252 return false; |
| 184 } | 253 } |
| 185 | 254 |
| 255 int64 URLRequestJob::GetByteReadCount() const { |
| 256 return filter_input_byte_count_; |
| 257 } |
| 258 |
| 186 int URLRequestJob::GetResponseCode() const { | 259 int URLRequestJob::GetResponseCode() const { |
| 187 return -1; | 260 return -1; |
| 188 } | 261 } |
| 189 | 262 |
| 190 int URLRequestJob::GetInputStreamBufferSize() const { | 263 int URLRequestJob::GetInputStreamBufferSize() const { |
| 191 return kFilterBufSize; | 264 return kFilterBufSize; |
| 192 } | 265 } |
| 193 | 266 |
| 194 // This function calls ReadData to get stream data. If a filter exists, passes | 267 void URLRequestJob::RecordPacketStats(StatisticSelector statistic) const { |
| 195 // the data to the attached filter. Then returns the output from filter back to | 268 if (!packet_timing_enabled_ || (final_packet_time_ == base::Time())) |
| 196 // the caller. | 269 return; |
| 197 bool URLRequestJob::Read(net::IOBuffer* buf, int buf_size, int *bytes_read) { | |
| 198 bool rv = false; | |
| 199 | 270 |
| 200 DCHECK_LT(buf_size, 1000000); // sanity check | 271 // Caller should verify that we're not cached content, but we can't always |
| 201 DCHECK(buf); | 272 // really check for it here because we may (at destruction time) call our own |
| 202 DCHECK(bytes_read); | 273 // class method and get a bogus const answer of false. This DCHECK only helps |
| 203 DCHECK(filtered_read_buffer_ == NULL); | 274 // when this method has a valid overridden definition. |
| 204 DCHECK_EQ(0, filtered_read_buffer_len_); | 275 DCHECK(!IsCachedContent()); |
| 205 | 276 |
| 206 *bytes_read = 0; | 277 base::TimeDelta duration = final_packet_time_ - request_time_snapshot_; |
| 278 switch (statistic) { |
| 279 case SDCH_DECODE: { |
| 280 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_Latency_F_a", duration, |
| 281 base::TimeDelta::FromMilliseconds(20), |
| 282 base::TimeDelta::FromMinutes(10), 100); |
| 283 UMA_HISTOGRAM_COUNTS_100("Sdch3.Network_Decode_Packets_b", |
| 284 static_cast<int>(observed_packet_count_)); |
| 285 UMA_HISTOGRAM_CUSTOM_COUNTS("Sdch3.Network_Decode_Bytes_Processed_b", |
| 286 static_cast<int>(bytes_observed_in_packets_), 500, 100000, 100); |
| 287 if (packet_times_.empty()) |
| 288 return; |
| 289 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_1st_To_Last_a", |
| 290 final_packet_time_ - packet_times_[0], |
| 291 base::TimeDelta::FromMilliseconds(20), |
| 292 base::TimeDelta::FromMinutes(10), 100); |
| 207 | 293 |
| 208 // Skip Filter if not present | 294 DCHECK(max_packets_timed_ >= kSdchPacketHistogramCount); |
| 209 if (!filter_.get()) { | 295 DCHECK(kSdchPacketHistogramCount > 4); |
| 210 rv = ReadRawDataHelper(buf, buf_size, bytes_read); | 296 if (packet_times_.size() <= 4) |
| 211 } else { | 297 return; |
| 212 // Save the caller's buffers while we do IO | 298 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_1st_To_2nd_c", |
| 213 // in the filter's buffers. | 299 packet_times_[1] - packet_times_[0], |
| 214 filtered_read_buffer_ = buf; | 300 base::TimeDelta::FromMilliseconds(1), |
| 215 filtered_read_buffer_len_ = buf_size; | 301 base::TimeDelta::FromSeconds(10), 100); |
| 302 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_2nd_To_3rd_c", |
| 303 packet_times_[2] - packet_times_[1], |
| 304 base::TimeDelta::FromMilliseconds(1), |
| 305 base::TimeDelta::FromSeconds(10), 100); |
| 306 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_3rd_To_4th_c", |
| 307 packet_times_[3] - packet_times_[2], |
| 308 base::TimeDelta::FromMilliseconds(1), |
| 309 base::TimeDelta::FromSeconds(10), 100); |
| 310 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_4th_To_5th_c", |
| 311 packet_times_[4] - packet_times_[3], |
| 312 base::TimeDelta::FromMilliseconds(1), |
| 313 base::TimeDelta::FromSeconds(10), 100); |
| 314 return; |
| 315 } |
| 316 case SDCH_PASSTHROUGH: { |
| 317 // Despite advertising a dictionary, we handled non-sdch compressed |
| 318 // content. |
| 319 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_Latency_F_a", |
| 320 duration, |
| 321 base::TimeDelta::FromMilliseconds(20), |
| 322 base::TimeDelta::FromMinutes(10), 100); |
| 323 UMA_HISTOGRAM_COUNTS_100("Sdch3.Network_Pass-through_Packets_b", |
| 324 observed_packet_count_); |
| 325 if (packet_times_.empty()) |
| 326 return; |
| 327 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_1st_To_Last_a", |
| 328 final_packet_time_ - packet_times_[0], |
| 329 base::TimeDelta::FromMilliseconds(20), |
| 330 base::TimeDelta::FromMinutes(10), 100); |
| 331 DCHECK(max_packets_timed_ >= kSdchPacketHistogramCount); |
| 332 DCHECK(kSdchPacketHistogramCount > 4); |
| 333 if (packet_times_.size() <= 4) |
| 334 return; |
| 335 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_1st_To_2nd_c", |
| 336 packet_times_[1] - packet_times_[0], |
| 337 base::TimeDelta::FromMilliseconds(1), |
| 338 base::TimeDelta::FromSeconds(10), 100); |
| 339 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_2nd_To_3rd_c", |
| 340 packet_times_[2] - packet_times_[1], |
| 341 base::TimeDelta::FromMilliseconds(1), |
| 342 base::TimeDelta::FromSeconds(10), 100); |
| 343 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_3rd_To_4th_c", |
| 344 packet_times_[3] - packet_times_[2], |
| 345 base::TimeDelta::FromMilliseconds(1), |
| 346 base::TimeDelta::FromSeconds(10), 100); |
| 347 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_4th_To_5th_c", |
| 348 packet_times_[4] - packet_times_[3], |
| 349 base::TimeDelta::FromMilliseconds(1), |
| 350 base::TimeDelta::FromSeconds(10), 100); |
| 351 return; |
| 352 } |
| 216 | 353 |
| 217 if (ReadFilteredData(bytes_read)) { | 354 case SDCH_EXPERIMENT_DECODE: { |
| 218 rv = true; // we have data to return | 355 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Decode", |
| 219 } else { | 356 duration, |
| 220 rv = false; // error, or a new IO is pending | 357 base::TimeDelta::FromMilliseconds(20), |
| 358 base::TimeDelta::FromMinutes(10), 100); |
| 359 // We already provided interpacket histograms above in the SDCH_DECODE |
| 360 // case, so we don't need them here. |
| 361 return; |
| 221 } | 362 } |
| 363 case SDCH_EXPERIMENT_HOLDBACK: { |
| 364 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback", |
| 365 duration, |
| 366 base::TimeDelta::FromMilliseconds(20), |
| 367 base::TimeDelta::FromMinutes(10), 100); |
| 368 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_1st_To_Last_a", |
| 369 final_packet_time_ - packet_times_[0], |
| 370 base::TimeDelta::FromMilliseconds(20), |
| 371 base::TimeDelta::FromMinutes(10), 100); |
| 372 |
| 373 DCHECK(max_packets_timed_ >= kSdchPacketHistogramCount); |
| 374 DCHECK(kSdchPacketHistogramCount > 4); |
| 375 if (packet_times_.size() <= 4) |
| 376 return; |
| 377 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_1st_To_2nd_c", |
| 378 packet_times_[1] - packet_times_[0], |
| 379 base::TimeDelta::FromMilliseconds(1), |
| 380 base::TimeDelta::FromSeconds(10), 100); |
| 381 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_2nd_To_3rd_c", |
| 382 packet_times_[2] - packet_times_[1], |
| 383 base::TimeDelta::FromMilliseconds(1), |
| 384 base::TimeDelta::FromSeconds(10), 100); |
| 385 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_3rd_To_4th_c", |
| 386 packet_times_[3] - packet_times_[2], |
| 387 base::TimeDelta::FromMilliseconds(1), |
| 388 base::TimeDelta::FromSeconds(10), 100); |
| 389 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_4th_To_5th_c", |
| 390 packet_times_[4] - packet_times_[3], |
| 391 base::TimeDelta::FromMilliseconds(1), |
| 392 base::TimeDelta::FromSeconds(10), 100); |
| 393 return; |
| 394 } |
| 395 default: |
| 396 NOTREACHED(); |
| 397 return; |
| 222 } | 398 } |
| 223 if (rv && *bytes_read == 0) | |
| 224 NotifyDone(URLRequestStatus()); | |
| 225 return rv; | |
| 226 } | 399 } |
| 227 | 400 |
| 228 void URLRequestJob::StopCaching() { | 401 URLRequestJob::~URLRequestJob() { |
| 229 // Nothing to do here. | 402 g_url_request_job_tracker.RemoveJob(this); |
| 230 } | |
| 231 | |
| 232 net::LoadState URLRequestJob::GetLoadState() const { | |
| 233 return net::LOAD_STATE_IDLE; | |
| 234 } | |
| 235 | |
| 236 uint64 URLRequestJob::GetUploadProgress() const { | |
| 237 return 0; | |
| 238 } | |
| 239 | |
| 240 bool URLRequestJob::GetCharset(std::string* charset) { | |
| 241 return false; | |
| 242 } | |
| 243 | |
| 244 void URLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { | |
| 245 } | |
| 246 | |
| 247 bool URLRequestJob::GetResponseCookies(std::vector<std::string>* cookies) { | |
| 248 return false; | |
| 249 } | |
| 250 | |
| 251 bool URLRequestJob::GetContentEncodings( | |
| 252 std::vector<Filter::FilterType>* encoding_types) { | |
| 253 return false; | |
| 254 } | |
| 255 | |
| 256 bool URLRequestJob::IsDownload() const { | |
| 257 return (load_flags_ & net::LOAD_IS_DOWNLOAD) != 0; | |
| 258 } | |
| 259 | |
| 260 bool URLRequestJob::IsSdchResponse() const { | |
| 261 return false; | |
| 262 } | |
| 263 | |
| 264 bool URLRequestJob::ReadRawDataForFilter(int* bytes_read) { | |
| 265 bool rv = false; | |
| 266 | |
| 267 DCHECK(bytes_read); | |
| 268 DCHECK(filter_.get()); | |
| 269 | |
| 270 *bytes_read = 0; | |
| 271 | |
| 272 // Get more pre-filtered data if needed. | |
| 273 // TODO(mbelshe): is it possible that the filter needs *MORE* data | |
| 274 // when there is some data already in the buffer? | |
| 275 if (!filter_->stream_data_len() && !is_done()) { | |
| 276 net::IOBuffer* stream_buffer = filter_->stream_buffer(); | |
| 277 int stream_buffer_size = filter_->stream_buffer_size(); | |
| 278 rv = ReadRawDataHelper(stream_buffer, stream_buffer_size, bytes_read); | |
| 279 } | |
| 280 return rv; | |
| 281 } | |
| 282 | |
| 283 void URLRequestJob::FollowRedirect(const GURL& location, int http_status_code) { | |
| 284 g_url_request_job_tracker.OnJobRedirect(this, location, http_status_code); | |
| 285 | |
| 286 int rv = request_->Redirect(location, http_status_code); | |
| 287 if (rv != net::OK) | |
| 288 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); | |
| 289 } | |
| 290 | |
| 291 void URLRequestJob::FilteredDataRead(int bytes_read) { | |
| 292 DCHECK(filter_.get()); // don't add data if there is no filter | |
| 293 filter_->FlushStreamBuffer(bytes_read); | |
| 294 } | |
| 295 | |
| 296 bool URLRequestJob::ReadFilteredData(int* bytes_read) { | |
| 297 DCHECK(filter_.get()); // don't add data if there is no filter | |
| 298 DCHECK(filtered_read_buffer_ != NULL); // we need to have a buffer to fill | |
| 299 DCHECK_GT(filtered_read_buffer_len_, 0); // sanity check | |
| 300 DCHECK_LT(filtered_read_buffer_len_, 1000000); // sanity check | |
| 301 DCHECK(raw_read_buffer_ == NULL); // there should be no raw read buffer yet | |
| 302 | |
| 303 bool rv = false; | |
| 304 *bytes_read = 0; | |
| 305 | |
| 306 if (is_done()) | |
| 307 return true; | |
| 308 | |
| 309 if (!filter_needs_more_output_space_ && !filter_->stream_data_len()) { | |
| 310 // We don't have any raw data to work with, so | |
| 311 // read from the socket. | |
| 312 int filtered_data_read; | |
| 313 if (ReadRawDataForFilter(&filtered_data_read)) { | |
| 314 if (filtered_data_read > 0) { | |
| 315 filter_->FlushStreamBuffer(filtered_data_read); // Give data to filter. | |
| 316 } else { | |
| 317 return true; // EOF | |
| 318 } | |
| 319 } else { | |
| 320 return false; // IO Pending (or error) | |
| 321 } | |
| 322 } | |
| 323 | |
| 324 if ((filter_->stream_data_len() || filter_needs_more_output_space_) | |
| 325 && !is_done()) { | |
| 326 // Get filtered data. | |
| 327 int filtered_data_len = filtered_read_buffer_len_; | |
| 328 Filter::FilterStatus status; | |
| 329 int output_buffer_size = filtered_data_len; | |
| 330 status = filter_->ReadData(filtered_read_buffer_->data(), | |
| 331 &filtered_data_len); | |
| 332 | |
| 333 if (filter_needs_more_output_space_ && 0 == filtered_data_len) { | |
| 334 // filter_needs_more_output_space_ was mistaken... there are no more bytes | |
| 335 // and we should have at least tried to fill up the filter's input buffer. | |
| 336 // Correct the state, and try again. | |
| 337 filter_needs_more_output_space_ = false; | |
| 338 return ReadFilteredData(bytes_read); | |
| 339 } | |
| 340 | |
| 341 switch (status) { | |
| 342 case Filter::FILTER_DONE: { | |
| 343 filter_needs_more_output_space_ = false; | |
| 344 *bytes_read = filtered_data_len; | |
| 345 rv = true; | |
| 346 break; | |
| 347 } | |
| 348 case Filter::FILTER_NEED_MORE_DATA: { | |
| 349 filter_needs_more_output_space_ = | |
| 350 (filtered_data_len == output_buffer_size); | |
| 351 // We have finished filtering all data currently in the buffer. | |
| 352 // There might be some space left in the output buffer. One can | |
| 353 // consider reading more data from the stream to feed the filter | |
| 354 // and filling up the output buffer. This leads to more complicated | |
| 355 // buffer management and data notification mechanisms. | |
| 356 // We can revisit this issue if there is a real perf need. | |
| 357 if (filtered_data_len > 0) { | |
| 358 *bytes_read = filtered_data_len; | |
| 359 rv = true; | |
| 360 } else { | |
| 361 // Read again since we haven't received enough data yet (e.g., we may | |
| 362 // not have a complete gzip header yet) | |
| 363 rv = ReadFilteredData(bytes_read); | |
| 364 } | |
| 365 break; | |
| 366 } | |
| 367 case Filter::FILTER_OK: { | |
| 368 filter_needs_more_output_space_ = | |
| 369 (filtered_data_len == output_buffer_size); | |
| 370 *bytes_read = filtered_data_len; | |
| 371 rv = true; | |
| 372 break; | |
| 373 } | |
| 374 case Filter::FILTER_ERROR: { | |
| 375 filter_needs_more_output_space_ = false; | |
| 376 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, | |
| 377 net::ERR_CONTENT_DECODING_FAILED)); | |
| 378 rv = false; | |
| 379 break; | |
| 380 } | |
| 381 default: { | |
| 382 NOTREACHED(); | |
| 383 filter_needs_more_output_space_ = false; | |
| 384 rv = false; | |
| 385 break; | |
| 386 } | |
| 387 } | |
| 388 } else { | |
| 389 // we are done, or there is no data left. | |
| 390 rv = true; | |
| 391 } | |
| 392 | |
| 393 if (rv) { | |
| 394 // When we successfully finished a read, we no longer need to | |
| 395 // save the caller's buffers. Release our reference. | |
| 396 filtered_read_buffer_ = NULL; | |
| 397 filtered_read_buffer_len_ = 0; | |
| 398 } | |
| 399 return rv; | |
| 400 } | |
| 401 | |
| 402 bool URLRequestJob::ReadRawDataHelper(net::IOBuffer* buf, int buf_size, | |
| 403 int* bytes_read) { | |
| 404 DCHECK(!request_->status().is_io_pending()); | |
| 405 DCHECK(raw_read_buffer_ == NULL); | |
| 406 | |
| 407 // Keep a pointer to the read buffer, so we have access to it in the | |
| 408 // OnRawReadComplete() callback in the event that the read completes | |
| 409 // asynchronously. | |
| 410 raw_read_buffer_ = buf; | |
| 411 bool rv = ReadRawData(buf, buf_size, bytes_read); | |
| 412 | |
| 413 if (!request_->status().is_io_pending()) { | |
| 414 // If the read completes synchronously, either success or failure, | |
| 415 // invoke the OnRawReadComplete callback so we can account for the | |
| 416 // completed read. | |
| 417 OnRawReadComplete(*bytes_read); | |
| 418 } | |
| 419 return rv; | |
| 420 } | |
| 421 | |
| 422 bool URLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size, | |
| 423 int *bytes_read) { | |
| 424 DCHECK(bytes_read); | |
| 425 *bytes_read = 0; | |
| 426 NotifyDone(URLRequestStatus()); | |
| 427 return false; | |
| 428 } | |
| 429 | |
| 430 URLRequestJobMetrics* URLRequestJob::RetrieveMetrics() { | |
| 431 if (is_profiling()) | |
| 432 return metrics_.release(); | |
| 433 else | |
| 434 return NULL; | |
| 435 } | 403 } |
| 436 | 404 |
| 437 void URLRequestJob::NotifyHeadersComplete() { | 405 void URLRequestJob::NotifyHeadersComplete() { |
| 438 if (!request_ || !request_->delegate()) | 406 if (!request_ || !request_->delegate()) |
| 439 return; // The request was destroyed, so there is no more work to do. | 407 return; // The request was destroyed, so there is no more work to do. |
| 440 | 408 |
| 441 if (has_handled_response_) | 409 if (has_handled_response_) |
| 442 return; | 410 return; |
| 443 | 411 |
| 444 DCHECK(!request_->status().is_io_pending()); | 412 DCHECK(!request_->status().is_io_pending()); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 } else { | 490 } else { |
| 523 // Chrome today only sends "Accept-Encoding" for compression schemes. | 491 // Chrome today only sends "Accept-Encoding" for compression schemes. |
| 524 // So, if there is a filter on the response, we know that the content | 492 // So, if there is a filter on the response, we know that the content |
| 525 // was compressed. | 493 // was compressed. |
| 526 is_compressed_ = true; | 494 is_compressed_ = true; |
| 527 } | 495 } |
| 528 | 496 |
| 529 request_->ResponseStarted(); | 497 request_->ResponseStarted(); |
| 530 } | 498 } |
| 531 | 499 |
| 532 void URLRequestJob::NotifyStartError(const URLRequestStatus &status) { | |
| 533 DCHECK(!has_handled_response_); | |
| 534 has_handled_response_ = true; | |
| 535 if (request_) { | |
| 536 request_->set_status(status); | |
| 537 request_->ResponseStarted(); | |
| 538 } | |
| 539 } | |
| 540 | |
| 541 void URLRequestJob::NotifyReadComplete(int bytes_read) { | 500 void URLRequestJob::NotifyReadComplete(int bytes_read) { |
| 542 if (!request_ || !request_->delegate()) | 501 if (!request_ || !request_->delegate()) |
| 543 return; // The request was destroyed, so there is no more work to do. | 502 return; // The request was destroyed, so there is no more work to do. |
| 544 | 503 |
| 545 // TODO(darin): Bug 1004233. Re-enable this test once all of the chrome | 504 // TODO(darin): Bug 1004233. Re-enable this test once all of the chrome |
| 546 // unit_tests have been fixed to not trip this. | 505 // unit_tests have been fixed to not trip this. |
| 547 //DCHECK(!request_->status().is_io_pending()); | 506 //DCHECK(!request_->status().is_io_pending()); |
| 548 | 507 |
| 549 // The headers should be complete before reads complete | 508 // The headers should be complete before reads complete |
| 550 DCHECK(has_handled_response_); | 509 DCHECK(has_handled_response_); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 572 if (ReadFilteredData(&filter_bytes_read)) { | 531 if (ReadFilteredData(&filter_bytes_read)) { |
| 573 postfilter_bytes_read_ += filter_bytes_read; | 532 postfilter_bytes_read_ += filter_bytes_read; |
| 574 request_->delegate()->OnReadCompleted(request_, filter_bytes_read); | 533 request_->delegate()->OnReadCompleted(request_, filter_bytes_read); |
| 575 } | 534 } |
| 576 } else { | 535 } else { |
| 577 postfilter_bytes_read_ += bytes_read; | 536 postfilter_bytes_read_ += bytes_read; |
| 578 request_->delegate()->OnReadCompleted(request_, bytes_read); | 537 request_->delegate()->OnReadCompleted(request_, bytes_read); |
| 579 } | 538 } |
| 580 } | 539 } |
| 581 | 540 |
| 541 void URLRequestJob::NotifyStartError(const URLRequestStatus &status) { |
| 542 DCHECK(!has_handled_response_); |
| 543 has_handled_response_ = true; |
| 544 if (request_) { |
| 545 request_->set_status(status); |
| 546 request_->ResponseStarted(); |
| 547 } |
| 548 } |
| 549 |
| 582 void URLRequestJob::NotifyDone(const URLRequestStatus &status) { | 550 void URLRequestJob::NotifyDone(const URLRequestStatus &status) { |
| 583 DCHECK(!done_) << "Job sending done notification twice"; | 551 DCHECK(!done_) << "Job sending done notification twice"; |
| 584 if (done_) | 552 if (done_) |
| 585 return; | 553 return; |
| 586 done_ = true; | 554 done_ = true; |
| 587 | 555 |
| 588 RecordCompressionHistograms(); | 556 RecordCompressionHistograms(); |
| 589 | 557 |
| 590 if (is_profiling() && metrics_->total_bytes_read_ > 0) { | 558 if (is_profiling() && metrics_->total_bytes_read_ > 0) { |
| 591 // There are valid IO statistics. Fill in other fields of metrics for | 559 // There are valid IO statistics. Fill in other fields of metrics for |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 net::ERR_ABORTED)); | 619 net::ERR_ABORTED)); |
| 652 } | 620 } |
| 653 } | 621 } |
| 654 | 622 |
| 655 void URLRequestJob::NotifyRestartRequired() { | 623 void URLRequestJob::NotifyRestartRequired() { |
| 656 DCHECK(!has_handled_response_); | 624 DCHECK(!has_handled_response_); |
| 657 if (GetStatus().status() != URLRequestStatus::CANCELED) | 625 if (GetStatus().status() != URLRequestStatus::CANCELED) |
| 658 request_->Restart(); | 626 request_->Restart(); |
| 659 } | 627 } |
| 660 | 628 |
| 661 bool URLRequestJob::FilterHasData() { | 629 bool URLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size, |
| 662 return filter_.get() && filter_->stream_data_len(); | 630 int *bytes_read) { |
| 631 DCHECK(bytes_read); |
| 632 *bytes_read = 0; |
| 633 NotifyDone(URLRequestStatus()); |
| 634 return false; |
| 663 } | 635 } |
| 664 | 636 |
| 665 void URLRequestJob::OnRawReadComplete(int bytes_read) { | 637 void URLRequestJob::FilteredDataRead(int bytes_read) { |
| 666 DCHECK(raw_read_buffer_); | 638 DCHECK(filter_.get()); // don't add data if there is no filter |
| 667 if (bytes_read > 0) { | 639 filter_->FlushStreamBuffer(bytes_read); |
| 668 RecordBytesRead(bytes_read); | |
| 669 } | |
| 670 raw_read_buffer_ = NULL; | |
| 671 } | 640 } |
| 672 | 641 |
| 673 void URLRequestJob::RecordBytesRead(int bytes_read) { | 642 bool URLRequestJob::ReadFilteredData(int* bytes_read) { |
| 674 if (is_profiling()) { | 643 DCHECK(filter_.get()); // don't add data if there is no filter |
| 675 ++(metrics_->number_of_read_IO_); | 644 DCHECK(filtered_read_buffer_ != NULL); // we need to have a buffer to fill |
| 676 metrics_->total_bytes_read_ += bytes_read; | 645 DCHECK_GT(filtered_read_buffer_len_, 0); // sanity check |
| 646 DCHECK_LT(filtered_read_buffer_len_, 1000000); // sanity check |
| 647 DCHECK(raw_read_buffer_ == NULL); // there should be no raw read buffer yet |
| 648 |
| 649 bool rv = false; |
| 650 *bytes_read = 0; |
| 651 |
| 652 if (is_done()) |
| 653 return true; |
| 654 |
| 655 if (!filter_needs_more_output_space_ && !filter_->stream_data_len()) { |
| 656 // We don't have any raw data to work with, so |
| 657 // read from the socket. |
| 658 int filtered_data_read; |
| 659 if (ReadRawDataForFilter(&filtered_data_read)) { |
| 660 if (filtered_data_read > 0) { |
| 661 filter_->FlushStreamBuffer(filtered_data_read); // Give data to filter. |
| 662 } else { |
| 663 return true; // EOF |
| 664 } |
| 665 } else { |
| 666 return false; // IO Pending (or error) |
| 667 } |
| 677 } | 668 } |
| 678 filter_input_byte_count_ += bytes_read; | 669 |
| 679 UpdatePacketReadTimes(); // Facilitate stats recording if it is active. | 670 if ((filter_->stream_data_len() || filter_needs_more_output_space_) |
| 680 g_url_request_job_tracker.OnBytesRead(this, raw_read_buffer_->data(), | 671 && !is_done()) { |
| 681 bytes_read); | 672 // Get filtered data. |
| 673 int filtered_data_len = filtered_read_buffer_len_; |
| 674 Filter::FilterStatus status; |
| 675 int output_buffer_size = filtered_data_len; |
| 676 status = filter_->ReadData(filtered_read_buffer_->data(), |
| 677 &filtered_data_len); |
| 678 |
| 679 if (filter_needs_more_output_space_ && 0 == filtered_data_len) { |
| 680 // filter_needs_more_output_space_ was mistaken... there are no more bytes |
| 681 // and we should have at least tried to fill up the filter's input buffer. |
| 682 // Correct the state, and try again. |
| 683 filter_needs_more_output_space_ = false; |
| 684 return ReadFilteredData(bytes_read); |
| 685 } |
| 686 |
| 687 switch (status) { |
| 688 case Filter::FILTER_DONE: { |
| 689 filter_needs_more_output_space_ = false; |
| 690 *bytes_read = filtered_data_len; |
| 691 rv = true; |
| 692 break; |
| 693 } |
| 694 case Filter::FILTER_NEED_MORE_DATA: { |
| 695 filter_needs_more_output_space_ = |
| 696 (filtered_data_len == output_buffer_size); |
| 697 // We have finished filtering all data currently in the buffer. |
| 698 // There might be some space left in the output buffer. One can |
| 699 // consider reading more data from the stream to feed the filter |
| 700 // and filling up the output buffer. This leads to more complicated |
| 701 // buffer management and data notification mechanisms. |
| 702 // We can revisit this issue if there is a real perf need. |
| 703 if (filtered_data_len > 0) { |
| 704 *bytes_read = filtered_data_len; |
| 705 rv = true; |
| 706 } else { |
| 707 // Read again since we haven't received enough data yet (e.g., we may |
| 708 // not have a complete gzip header yet) |
| 709 rv = ReadFilteredData(bytes_read); |
| 710 } |
| 711 break; |
| 712 } |
| 713 case Filter::FILTER_OK: { |
| 714 filter_needs_more_output_space_ = |
| 715 (filtered_data_len == output_buffer_size); |
| 716 *bytes_read = filtered_data_len; |
| 717 rv = true; |
| 718 break; |
| 719 } |
| 720 case Filter::FILTER_ERROR: { |
| 721 filter_needs_more_output_space_ = false; |
| 722 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, |
| 723 net::ERR_CONTENT_DECODING_FAILED)); |
| 724 rv = false; |
| 725 break; |
| 726 } |
| 727 default: { |
| 728 NOTREACHED(); |
| 729 filter_needs_more_output_space_ = false; |
| 730 rv = false; |
| 731 break; |
| 732 } |
| 733 } |
| 734 } else { |
| 735 // we are done, or there is no data left. |
| 736 rv = true; |
| 737 } |
| 738 |
| 739 if (rv) { |
| 740 // When we successfully finished a read, we no longer need to |
| 741 // save the caller's buffers. Release our reference. |
| 742 filtered_read_buffer_ = NULL; |
| 743 filtered_read_buffer_len_ = 0; |
| 744 } |
| 745 return rv; |
| 746 } |
| 747 |
| 748 void URLRequestJob::EnablePacketCounting(size_t max_packets_timed) { |
| 749 if (max_packets_timed_ < max_packets_timed) |
| 750 max_packets_timed_ = max_packets_timed; |
| 751 packet_timing_enabled_ = true; |
| 682 } | 752 } |
| 683 | 753 |
| 684 const URLRequestStatus URLRequestJob::GetStatus() { | 754 const URLRequestStatus URLRequestJob::GetStatus() { |
| 685 if (request_) | 755 if (request_) |
| 686 return request_->status(); | 756 return request_->status(); |
| 687 // If the request is gone, we must be cancelled. | 757 // If the request is gone, we must be cancelled. |
| 688 return URLRequestStatus(URLRequestStatus::CANCELED, | 758 return URLRequestStatus(URLRequestStatus::CANCELED, |
| 689 net::ERR_ABORTED); | 759 net::ERR_ABORTED); |
| 690 } | 760 } |
| 691 | 761 |
| 692 void URLRequestJob::SetStatus(const URLRequestStatus &status) { | 762 void URLRequestJob::SetStatus(const URLRequestStatus &status) { |
| 693 if (request_) | 763 if (request_) |
| 694 request_->set_status(status); | 764 request_->set_status(status); |
| 695 } | 765 } |
| 696 | 766 |
| 767 bool URLRequestJob::ReadRawDataForFilter(int* bytes_read) { |
| 768 bool rv = false; |
| 769 |
| 770 DCHECK(bytes_read); |
| 771 DCHECK(filter_.get()); |
| 772 |
| 773 *bytes_read = 0; |
| 774 |
| 775 // Get more pre-filtered data if needed. |
| 776 // TODO(mbelshe): is it possible that the filter needs *MORE* data |
| 777 // when there is some data already in the buffer? |
| 778 if (!filter_->stream_data_len() && !is_done()) { |
| 779 net::IOBuffer* stream_buffer = filter_->stream_buffer(); |
| 780 int stream_buffer_size = filter_->stream_buffer_size(); |
| 781 rv = ReadRawDataHelper(stream_buffer, stream_buffer_size, bytes_read); |
| 782 } |
| 783 return rv; |
| 784 } |
| 785 |
| 786 bool URLRequestJob::ReadRawDataHelper(net::IOBuffer* buf, int buf_size, |
| 787 int* bytes_read) { |
| 788 DCHECK(!request_->status().is_io_pending()); |
| 789 DCHECK(raw_read_buffer_ == NULL); |
| 790 |
| 791 // Keep a pointer to the read buffer, so we have access to it in the |
| 792 // OnRawReadComplete() callback in the event that the read completes |
| 793 // asynchronously. |
| 794 raw_read_buffer_ = buf; |
| 795 bool rv = ReadRawData(buf, buf_size, bytes_read); |
| 796 |
| 797 if (!request_->status().is_io_pending()) { |
| 798 // If the read completes synchronously, either success or failure, |
| 799 // invoke the OnRawReadComplete callback so we can account for the |
| 800 // completed read. |
| 801 OnRawReadComplete(*bytes_read); |
| 802 } |
| 803 return rv; |
| 804 } |
| 805 |
| 806 void URLRequestJob::FollowRedirect(const GURL& location, int http_status_code) { |
| 807 g_url_request_job_tracker.OnJobRedirect(this, location, http_status_code); |
| 808 |
| 809 int rv = request_->Redirect(location, http_status_code); |
| 810 if (rv != net::OK) |
| 811 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); |
| 812 } |
| 813 |
| 814 void URLRequestJob::OnRawReadComplete(int bytes_read) { |
| 815 DCHECK(raw_read_buffer_); |
| 816 if (bytes_read > 0) { |
| 817 RecordBytesRead(bytes_read); |
| 818 } |
| 819 raw_read_buffer_ = NULL; |
| 820 } |
| 821 |
| 822 void URLRequestJob::RecordBytesRead(int bytes_read) { |
| 823 if (is_profiling()) { |
| 824 ++(metrics_->number_of_read_IO_); |
| 825 metrics_->total_bytes_read_ += bytes_read; |
| 826 } |
| 827 filter_input_byte_count_ += bytes_read; |
| 828 UpdatePacketReadTimes(); // Facilitate stats recording if it is active. |
| 829 g_url_request_job_tracker.OnBytesRead(this, raw_read_buffer_->data(), |
| 830 bytes_read); |
| 831 } |
| 832 |
| 833 bool URLRequestJob::FilterHasData() { |
| 834 return filter_.get() && filter_->stream_data_len(); |
| 835 } |
| 836 |
| 697 void URLRequestJob::UpdatePacketReadTimes() { | 837 void URLRequestJob::UpdatePacketReadTimes() { |
| 698 if (!packet_timing_enabled_) | 838 if (!packet_timing_enabled_) |
| 699 return; | 839 return; |
| 700 | 840 |
| 701 if (filter_input_byte_count_ <= bytes_observed_in_packets_) { | 841 if (filter_input_byte_count_ <= bytes_observed_in_packets_) { |
| 702 DCHECK(filter_input_byte_count_ == bytes_observed_in_packets_); | 842 DCHECK(filter_input_byte_count_ == bytes_observed_in_packets_); |
| 703 return; // No new bytes have arrived. | 843 return; // No new bytes have arrived. |
| 704 } | 844 } |
| 705 | 845 |
| 706 if (!bytes_observed_in_packets_) | 846 if (!bytes_observed_in_packets_) |
| 707 request_time_snapshot_ = GetRequestTime(); | 847 request_time_snapshot_ = GetRequestTime(); |
| 708 | 848 |
| 709 final_packet_time_ = base::Time::Now(); | 849 final_packet_time_ = base::Time::Now(); |
| 710 const size_t kTypicalPacketSize = 1430; | 850 const size_t kTypicalPacketSize = 1430; |
| 711 while (filter_input_byte_count_ > bytes_observed_in_packets_) { | 851 while (filter_input_byte_count_ > bytes_observed_in_packets_) { |
| 712 ++observed_packet_count_; | 852 ++observed_packet_count_; |
| 713 if (max_packets_timed_ > packet_times_.size()) { | 853 if (max_packets_timed_ > packet_times_.size()) { |
| 714 packet_times_.push_back(final_packet_time_); | 854 packet_times_.push_back(final_packet_time_); |
| 715 DCHECK(static_cast<size_t>(observed_packet_count_) == | 855 DCHECK(static_cast<size_t>(observed_packet_count_) == |
| 716 packet_times_.size()); | 856 packet_times_.size()); |
| 717 } | 857 } |
| 718 bytes_observed_in_packets_ += kTypicalPacketSize; | 858 bytes_observed_in_packets_ += kTypicalPacketSize; |
| 719 } | 859 } |
| 720 // Since packets may not be full, we'll remember the number of bytes we've | 860 // Since packets may not be full, we'll remember the number of bytes we've |
| 721 // accounted for in packets thus far. | 861 // accounted for in packets thus far. |
| 722 bytes_observed_in_packets_ = filter_input_byte_count_; | 862 bytes_observed_in_packets_ = filter_input_byte_count_; |
| 723 } | 863 } |
| 724 | 864 |
| 725 void URLRequestJob::EnablePacketCounting(size_t max_packets_timed) { | |
| 726 if (max_packets_timed_ < max_packets_timed) | |
| 727 max_packets_timed_ = max_packets_timed; | |
| 728 packet_timing_enabled_ = true; | |
| 729 } | |
| 730 | |
| 731 void URLRequestJob::RecordPacketStats(StatisticSelector statistic) const { | |
| 732 if (!packet_timing_enabled_ || (final_packet_time_ == base::Time())) | |
| 733 return; | |
| 734 | |
| 735 // Caller should verify that we're not cached content, but we can't always | |
| 736 // really check for it here because we may (at destruction time) call our own | |
| 737 // class method and get a bogus const answer of false. This DCHECK only helps | |
| 738 // when this method has a valid overridden definition. | |
| 739 DCHECK(!IsCachedContent()); | |
| 740 | |
| 741 base::TimeDelta duration = final_packet_time_ - request_time_snapshot_; | |
| 742 switch (statistic) { | |
| 743 case SDCH_DECODE: { | |
| 744 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_Latency_F_a", duration, | |
| 745 base::TimeDelta::FromMilliseconds(20), | |
| 746 base::TimeDelta::FromMinutes(10), 100); | |
| 747 UMA_HISTOGRAM_COUNTS_100("Sdch3.Network_Decode_Packets_b", | |
| 748 static_cast<int>(observed_packet_count_)); | |
| 749 UMA_HISTOGRAM_CUSTOM_COUNTS("Sdch3.Network_Decode_Bytes_Processed_b", | |
| 750 static_cast<int>(bytes_observed_in_packets_), 500, 100000, 100); | |
| 751 if (packet_times_.empty()) | |
| 752 return; | |
| 753 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_1st_To_Last_a", | |
| 754 final_packet_time_ - packet_times_[0], | |
| 755 base::TimeDelta::FromMilliseconds(20), | |
| 756 base::TimeDelta::FromMinutes(10), 100); | |
| 757 | |
| 758 DCHECK(max_packets_timed_ >= kSdchPacketHistogramCount); | |
| 759 DCHECK(kSdchPacketHistogramCount > 4); | |
| 760 if (packet_times_.size() <= 4) | |
| 761 return; | |
| 762 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_1st_To_2nd_c", | |
| 763 packet_times_[1] - packet_times_[0], | |
| 764 base::TimeDelta::FromMilliseconds(1), | |
| 765 base::TimeDelta::FromSeconds(10), 100); | |
| 766 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_2nd_To_3rd_c", | |
| 767 packet_times_[2] - packet_times_[1], | |
| 768 base::TimeDelta::FromMilliseconds(1), | |
| 769 base::TimeDelta::FromSeconds(10), 100); | |
| 770 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_3rd_To_4th_c", | |
| 771 packet_times_[3] - packet_times_[2], | |
| 772 base::TimeDelta::FromMilliseconds(1), | |
| 773 base::TimeDelta::FromSeconds(10), 100); | |
| 774 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_4th_To_5th_c", | |
| 775 packet_times_[4] - packet_times_[3], | |
| 776 base::TimeDelta::FromMilliseconds(1), | |
| 777 base::TimeDelta::FromSeconds(10), 100); | |
| 778 return; | |
| 779 } | |
| 780 case SDCH_PASSTHROUGH: { | |
| 781 // Despite advertising a dictionary, we handled non-sdch compressed | |
| 782 // content. | |
| 783 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_Latency_F_a", | |
| 784 duration, | |
| 785 base::TimeDelta::FromMilliseconds(20), | |
| 786 base::TimeDelta::FromMinutes(10), 100); | |
| 787 UMA_HISTOGRAM_COUNTS_100("Sdch3.Network_Pass-through_Packets_b", | |
| 788 observed_packet_count_); | |
| 789 if (packet_times_.empty()) | |
| 790 return; | |
| 791 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_1st_To_Last_a", | |
| 792 final_packet_time_ - packet_times_[0], | |
| 793 base::TimeDelta::FromMilliseconds(20), | |
| 794 base::TimeDelta::FromMinutes(10), 100); | |
| 795 DCHECK(max_packets_timed_ >= kSdchPacketHistogramCount); | |
| 796 DCHECK(kSdchPacketHistogramCount > 4); | |
| 797 if (packet_times_.size() <= 4) | |
| 798 return; | |
| 799 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_1st_To_2nd_c", | |
| 800 packet_times_[1] - packet_times_[0], | |
| 801 base::TimeDelta::FromMilliseconds(1), | |
| 802 base::TimeDelta::FromSeconds(10), 100); | |
| 803 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_2nd_To_3rd_c", | |
| 804 packet_times_[2] - packet_times_[1], | |
| 805 base::TimeDelta::FromMilliseconds(1), | |
| 806 base::TimeDelta::FromSeconds(10), 100); | |
| 807 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_3rd_To_4th_c", | |
| 808 packet_times_[3] - packet_times_[2], | |
| 809 base::TimeDelta::FromMilliseconds(1), | |
| 810 base::TimeDelta::FromSeconds(10), 100); | |
| 811 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_4th_To_5th_c", | |
| 812 packet_times_[4] - packet_times_[3], | |
| 813 base::TimeDelta::FromMilliseconds(1), | |
| 814 base::TimeDelta::FromSeconds(10), 100); | |
| 815 return; | |
| 816 } | |
| 817 | |
| 818 case SDCH_EXPERIMENT_DECODE: { | |
| 819 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Decode", | |
| 820 duration, | |
| 821 base::TimeDelta::FromMilliseconds(20), | |
| 822 base::TimeDelta::FromMinutes(10), 100); | |
| 823 // We already provided interpacket histograms above in the SDCH_DECODE | |
| 824 // case, so we don't need them here. | |
| 825 return; | |
| 826 } | |
| 827 case SDCH_EXPERIMENT_HOLDBACK: { | |
| 828 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback", | |
| 829 duration, | |
| 830 base::TimeDelta::FromMilliseconds(20), | |
| 831 base::TimeDelta::FromMinutes(10), 100); | |
| 832 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_1st_To_Last_a", | |
| 833 final_packet_time_ - packet_times_[0], | |
| 834 base::TimeDelta::FromMilliseconds(20), | |
| 835 base::TimeDelta::FromMinutes(10), 100); | |
| 836 | |
| 837 DCHECK(max_packets_timed_ >= kSdchPacketHistogramCount); | |
| 838 DCHECK(kSdchPacketHistogramCount > 4); | |
| 839 if (packet_times_.size() <= 4) | |
| 840 return; | |
| 841 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_1st_To_2nd_c", | |
| 842 packet_times_[1] - packet_times_[0], | |
| 843 base::TimeDelta::FromMilliseconds(1), | |
| 844 base::TimeDelta::FromSeconds(10), 100); | |
| 845 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_2nd_To_3rd_c", | |
| 846 packet_times_[2] - packet_times_[1], | |
| 847 base::TimeDelta::FromMilliseconds(1), | |
| 848 base::TimeDelta::FromSeconds(10), 100); | |
| 849 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_3rd_To_4th_c", | |
| 850 packet_times_[3] - packet_times_[2], | |
| 851 base::TimeDelta::FromMilliseconds(1), | |
| 852 base::TimeDelta::FromSeconds(10), 100); | |
| 853 UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_4th_To_5th_c", | |
| 854 packet_times_[4] - packet_times_[3], | |
| 855 base::TimeDelta::FromMilliseconds(1), | |
| 856 base::TimeDelta::FromSeconds(10), 100); | |
| 857 return; | |
| 858 } | |
| 859 default: | |
| 860 NOTREACHED(); | |
| 861 return; | |
| 862 } | |
| 863 } | |
| 864 | |
| 865 // The common type of histogram we use for all compression-tracking histograms. | 865 // The common type of histogram we use for all compression-tracking histograms. |
| 866 #define COMPRESSION_HISTOGRAM(name, sample) \ | 866 #define COMPRESSION_HISTOGRAM(name, sample) \ |
| 867 do { \ | 867 do { \ |
| 868 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.Compress." name, sample, \ | 868 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.Compress." name, sample, \ |
| 869 500, 1000000, 100); \ | 869 500, 1000000, 100); \ |
| 870 } while(0) | 870 } while(0) |
| 871 | 871 |
| 872 void URLRequestJob::RecordCompressionHistograms() { | 872 void URLRequestJob::RecordCompressionHistograms() { |
| 873 if (IsCachedContent() || // Don't record cached content | 873 if (IsCachedContent() || // Don't record cached content |
| 874 !GetStatus().is_success() || // Don't record failed content | 874 !GetStatus().is_success() || // Don't record failed content |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 927 | 927 |
| 928 if (is_compressed_) { | 928 if (is_compressed_) { |
| 929 COMPRESSION_HISTOGRAM("NoProxy.BytesBeforeCompression", compressed_B); | 929 COMPRESSION_HISTOGRAM("NoProxy.BytesBeforeCompression", compressed_B); |
| 930 COMPRESSION_HISTOGRAM("NoProxy.BytesAfterCompression", decompressed_B); | 930 COMPRESSION_HISTOGRAM("NoProxy.BytesAfterCompression", decompressed_B); |
| 931 } else { | 931 } else { |
| 932 COMPRESSION_HISTOGRAM("NoProxy.ShouldHaveBeenCompressed", decompressed_B); | 932 COMPRESSION_HISTOGRAM("NoProxy.ShouldHaveBeenCompressed", decompressed_B); |
| 933 } | 933 } |
| 934 } | 934 } |
| 935 | 935 |
| 936 } // namespace net | 936 } // namespace net |
| OLD | NEW |