Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "cronet_url_request_adapter.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/location.h" | |
| 9 #include "base/logging.h" | |
| 10 #include "components/cronet/android/cronet_url_request_context_adapter.h" | |
| 11 #include "components/cronet/android/wrapped_channel_upload_element_reader.h" | |
| 12 #include "net/base/io_buffer.h" | |
| 13 #include "net/base/load_flags.h" | |
| 14 #include "net/http/http_status_code.h" | |
| 15 #include "net/url_request/redirect_info.h" | |
| 16 #include "net/url_request/url_request_context.h" | |
| 17 | |
| 18 namespace cronet { | |
| 19 | |
| 20 static const size_t kBufferSizeIncrement = 32768; | |
| 21 | |
| 22 CronetURLRequestAdapter::CronetURLRequestAdapter( | |
| 23 CronetURLRequestContextAdapter* context, | |
| 24 CronetURLRequestAdapterDelegate* delegate, | |
| 25 GURL url, | |
| 26 net::RequestPriority priority) | |
| 27 : method_("GET"), | |
| 28 read_buffer_(new net::IOBufferWithSize(kBufferSizeIncrement)), | |
| 29 http_status_code_(0), | |
| 30 called_to_delegate_(false), | |
| 31 cancel_soon_(false) { | |
|
xunjieli
2014/10/22 21:02:16
nit: Not exactly sure what cancel_soon_ does from
mef
2014/10/24 03:31:42
Done.
| |
| 32 context_ = context; | |
| 33 delegate_ = delegate; | |
| 34 url_ = url; | |
| 35 priority_ = priority; | |
| 36 } | |
| 37 | |
| 38 CronetURLRequestAdapter::~CronetURLRequestAdapter() { | |
| 39 url_request_.reset(); | |
| 40 } | |
| 41 | |
| 42 void CronetURLRequestAdapter::SetMethod(const std::string& method) { | |
| 43 method_ = method; | |
| 44 } | |
| 45 | |
| 46 void CronetURLRequestAdapter::AddRequestHeader(const std::string& name, | |
| 47 const std::string& value) { | |
| 48 request_headers_.SetHeader(name, value); | |
| 49 } | |
| 50 | |
| 51 net::HttpResponseHeaders* CronetURLRequestAdapter::GetResponseHeaders() const { | |
| 52 DCHECK(IsOnNetworkThread()); | |
| 53 if (url_request_ == NULL) | |
| 54 return NULL; | |
| 55 return url_request_->response_headers(); | |
| 56 } | |
| 57 | |
| 58 std::string CronetURLRequestAdapter::GetNegotiatedProtocol() const { | |
| 59 DCHECK(IsOnNetworkThread()); | |
| 60 if (url_request_ == NULL) | |
| 61 return std::string(); | |
| 62 return url_request_->response_info().npn_negotiated_protocol; | |
| 63 } | |
| 64 | |
| 65 bool CronetURLRequestAdapter::GetWasCached() const { | |
| 66 DCHECK(IsOnNetworkThread()); | |
| 67 if (url_request_ == NULL) | |
| 68 return false; | |
| 69 return url_request_->response_info().was_cached; | |
| 70 } | |
| 71 | |
| 72 int64 CronetURLRequestAdapter::GetTotalReceivedBytes() const { | |
| 73 DCHECK(IsOnNetworkThread()); | |
| 74 if (url_request_ == NULL) | |
| 75 return 0; | |
| 76 return url_request_->GetTotalReceivedBytes(); | |
| 77 } | |
| 78 | |
| 79 void CronetURLRequestAdapter::Start() { | |
| 80 DCHECK(!IsOnNetworkThread()); | |
| 81 context_->GetNetworkTaskRunner()->PostTask( | |
| 82 FROM_HERE, | |
| 83 base::Bind(&CronetURLRequestAdapter::StartOnNetworkThread, | |
| 84 base::Unretained(this))); | |
| 85 } | |
| 86 | |
| 87 void CronetURLRequestAdapter::FollowDeferredRedirect() { | |
| 88 DCHECK(!IsOnNetworkThread()); | |
| 89 context_->GetNetworkTaskRunner()->PostTask( | |
| 90 FROM_HERE, | |
| 91 base::Bind( | |
| 92 &CronetURLRequestAdapter::FollowDeferredRedirectOnNetworkThread, | |
| 93 base::Unretained(this))); | |
| 94 } | |
| 95 | |
| 96 // Receive more data. | |
| 97 void CronetURLRequestAdapter::ReadData() { | |
| 98 DCHECK(!IsOnNetworkThread()); | |
| 99 context_->GetNetworkTaskRunner()->PostTask( | |
| 100 FROM_HERE, | |
| 101 base::Bind(&CronetURLRequestAdapter::ReadDataOnNetworkThread, | |
| 102 base::Unretained(this))); | |
| 103 } | |
| 104 | |
| 105 void CronetURLRequestAdapter::Cancel() { | |
| 106 DCHECK(!IsOnNetworkThread()); | |
| 107 context_->GetNetworkTaskRunner()->PostTask( | |
| 108 FROM_HERE, | |
| 109 base::Bind(&CronetURLRequestAdapter::CancelOnNetworkThread, | |
| 110 base::Unretained(this))); | |
| 111 } | |
| 112 | |
| 113 void CronetURLRequestAdapter::Destroy() { | |
| 114 DCHECK(!IsOnNetworkThread()); | |
| 115 context_->GetNetworkTaskRunner()->DeleteSoon(FROM_HERE, this); | |
| 116 } | |
| 117 | |
| 118 // net::URLRequest::Delegate overrides (called on network thread). | |
| 119 void CronetURLRequestAdapter::OnReceivedRedirect( | |
| 120 net::URLRequest* request, | |
| 121 const net::RedirectInfo& redirect_info, | |
| 122 bool* defer_redirect) { | |
| 123 DCHECK(request->status().is_success()); | |
| 124 called_to_delegate_ = true; | |
| 125 delegate_->OnRedirect(this, redirect_info.new_url); | |
| 126 *defer_redirect = true; | |
| 127 } | |
| 128 | |
| 129 void CronetURLRequestAdapter::OnResponseStarted(net::URLRequest* request) { | |
| 130 if (!CheckStatus(request)) | |
| 131 return; | |
| 132 http_status_code_ = request->GetResponseCode(); | |
|
mmenke
2014/10/23 16:26:00
Think it's simpler to pass this in to the delegate
mef
2014/10/24 03:31:43
Ack. Not sure how it helps, but I'll think about i
mmenke
2014/10/24 03:46:19
How it helps: One less accessor method, one less
| |
| 133 called_to_delegate_ = true; | |
| 134 delegate_->OnResponseStarted(this); | |
| 135 } | |
| 136 | |
| 137 void CronetURLRequestAdapter::OnReadCompleted(net::URLRequest* request, | |
| 138 int bytes_read) { | |
| 139 if (!CheckStatus(request)) | |
| 140 return; | |
| 141 called_to_delegate_ = true; | |
| 142 if (bytes_read != 0) { | |
| 143 delegate_->OnBytesRead(this, bytes_read); | |
| 144 } else { | |
| 145 delegate_->OnRequestFinished(this); | |
| 146 } | |
| 147 } | |
| 148 bool CronetURLRequestAdapter::IsOnNetworkThread() const { | |
| 149 return context_->GetNetworkTaskRunner()->BelongsToCurrentThread(); | |
| 150 } | |
| 151 | |
| 152 void CronetURLRequestAdapter::StartOnNetworkThread() { | |
| 153 DCHECK(IsOnNetworkThread()); | |
| 154 if (cancel_soon_) | |
| 155 return; | |
| 156 | |
| 157 VLOG(1) << "Starting chromium request: " | |
| 158 << url_.possibly_invalid_spec().c_str() | |
| 159 << " priority: " << RequestPriorityToString(priority_); | |
| 160 url_request_ = context_->GetURLRequestContext()->CreateRequest( | |
| 161 url_, net::DEFAULT_PRIORITY, this, NULL); | |
| 162 url_request_->SetLoadFlags(net::LOAD_DISABLE_CACHE | | |
| 163 net::LOAD_DO_NOT_SAVE_COOKIES | | |
| 164 net::LOAD_DO_NOT_SEND_COOKIES); | |
| 165 url_request_->set_method(method_); | |
| 166 url_request_->SetExtraRequestHeaders(request_headers_); | |
| 167 if (!request_headers_.HasHeader(net::HttpRequestHeaders::kUserAgent)) { | |
| 168 std::string user_agent; | |
| 169 user_agent = context_->GetUserAgent(url_); | |
| 170 url_request_->SetExtraRequestHeaderByName( | |
| 171 net::HttpRequestHeaders::kUserAgent, user_agent, true /* override */); | |
| 172 } | |
| 173 | |
| 174 url_request_->SetPriority(priority_); | |
| 175 url_request_->Start(); | |
| 176 } | |
| 177 | |
| 178 void CronetURLRequestAdapter::FollowDeferredRedirectOnNetworkThread() { | |
| 179 DCHECK(IsOnNetworkThread()); | |
| 180 if (WasCanceledWhileCalledToDelegate()) | |
| 181 return; | |
| 182 | |
| 183 url_request_->FollowDeferredRedirect(); | |
| 184 } | |
| 185 | |
| 186 // Reads all available data or starts an asynchronous read. | |
| 187 void CronetURLRequestAdapter::ReadDataOnNetworkThread() { | |
| 188 DCHECK(IsOnNetworkThread()); | |
| 189 if (WasCanceledWhileCalledToDelegate()) | |
| 190 return; | |
| 191 int bytes_read = 0; | |
| 192 // If read completes synchronously, pass data to delegate. | |
| 193 if (url_request_->Read( | |
| 194 read_buffer_.get(), read_buffer_->size(), &bytes_read)) { | |
| 195 OnReadCompleted(url_request_.get(), bytes_read); | |
| 196 } else if (url_request_->status().status() != | |
| 197 net::URLRequestStatus::IO_PENDING) { | |
| 198 OnReadCompleted(url_request_.get(), -1); | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 void CronetURLRequestAdapter::CancelOnNetworkThread() { | |
| 203 DCHECK(IsOnNetworkThread()); | |
| 204 VLOG(1) << "Cancelling chromium request: " << url_.possibly_invalid_spec(); | |
| 205 | |
| 206 if (called_to_delegate_) { | |
| 207 cancel_soon_ = true; | |
| 208 return; | |
| 209 } | |
| 210 | |
| 211 if (url_request_ != NULL) | |
| 212 url_request_->Cancel(); | |
| 213 | |
| 214 delegate_->OnRequestCanceled(this); | |
| 215 } | |
| 216 | |
| 217 bool CronetURLRequestAdapter::WasCanceledWhileCalledToDelegate() { | |
| 218 DCHECK(IsOnNetworkThread()); | |
| 219 DCHECK(called_to_delegate_); | |
| 220 called_to_delegate_ = false; | |
| 221 if (cancel_soon_) { | |
| 222 CancelOnNetworkThread(); | |
| 223 return true; | |
| 224 } | |
| 225 return false; | |
| 226 } | |
| 227 | |
| 228 bool CronetURLRequestAdapter::CheckStatus(net::URLRequest* request) { | |
| 229 DCHECK_NE(net::URLRequestStatus::IO_PENDING, url_request_->status().status()); | |
| 230 DCHECK_EQ(request, url_request_); | |
| 231 if (url_request_->status().is_success()) | |
| 232 return true; | |
| 233 VLOG(1) << "Error " << url_request_->status().error() | |
| 234 << " on chromium request: " << url_.possibly_invalid_spec(); | |
| 235 called_to_delegate_ = true; | |
| 236 delegate_->OnError(this, url_request_->status().error()); | |
| 237 return false; | |
| 238 } | |
| 239 | |
| 240 unsigned char* CronetURLRequestAdapter::Data() const { | |
| 241 return reinterpret_cast<unsigned char*>(read_buffer_->data()); | |
| 242 } | |
| 243 | |
| 244 } // namespace cronet | |
| OLD | NEW |