OLD | NEW |
1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/appcache/appcache_url_loader_job.h" | 5 #include "content/browser/appcache/appcache_url_loader_job.h" |
6 | 6 |
7 #include "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
8 #include "content/browser/appcache/appcache_histograms.h" | 8 #include "content/browser/appcache/appcache_histograms.h" |
9 #include "content/browser/appcache/appcache_subresource_url_factory.h" | 9 #include "content/browser/appcache/appcache_subresource_url_factory.h" |
| 10 #include "content/browser/appcache/appcache_url_loader_request.h" |
10 #include "content/browser/url_loader_factory_getter.h" | 11 #include "content/browser/url_loader_factory_getter.h" |
11 #include "content/common/net_adapters.h" | 12 #include "content/common/net_adapters.h" |
12 #include "content/public/common/resource_type.h" | 13 #include "content/public/common/resource_type.h" |
13 #include "net/http/http_status_code.h" | 14 #include "net/http/http_status_code.h" |
14 | 15 |
15 namespace content { | 16 namespace content { |
16 | 17 |
17 SubresourceLoadInfo::SubresourceLoadInfo() | 18 SubresourceLoadInfo::SubresourceLoadInfo() |
18 : routing_id(-1), request_id(-1), options(0) {} | 19 : routing_id(-1), request_id(-1), options(0) {} |
19 | 20 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 AppCacheHistograms::AddNetworkJobStartDelaySample(base::TimeTicks::Now() - | 70 AppCacheHistograms::AddNetworkJobStartDelaySample(base::TimeTicks::Now() - |
70 start_time_tick_); | 71 start_time_tick_); |
71 | 72 |
72 if (IsResourceTypeFrame(request_.resource_type)) { | 73 if (IsResourceTypeFrame(request_.resource_type)) { |
73 DCHECK(!main_resource_loader_callback_.is_null()); | 74 DCHECK(!main_resource_loader_callback_.is_null()); |
74 // In network service land, if we are processing a navigation request, we | 75 // In network service land, if we are processing a navigation request, we |
75 // need to inform the loader callback that we are not going to handle this | 76 // need to inform the loader callback that we are not going to handle this |
76 // request. The loader callback is valid only for navigation requests. | 77 // request. The loader callback is valid only for navigation requests. |
77 std::move(main_resource_loader_callback_).Run(StartLoaderCallback()); | 78 std::move(main_resource_loader_callback_).Run(StartLoaderCallback()); |
78 } else { | 79 } else { |
| 80 mojom::URLLoaderClientPtr client_ptr; |
| 81 network_loader_client_binding_.Bind(mojo::MakeRequest(&client_ptr)); |
| 82 |
79 default_url_loader_factory_getter_->GetNetworkFactory() | 83 default_url_loader_factory_getter_->GetNetworkFactory() |
80 ->get() | 84 ->get() |
81 ->CreateLoaderAndStart( | 85 ->CreateLoaderAndStart( |
82 mojo::MakeRequest(&network_loader_request_), | 86 mojo::MakeRequest(&network_loader_), |
83 subresource_load_info_->routing_id, | 87 subresource_load_info_->routing_id, |
84 subresource_load_info_->request_id, subresource_load_info_->options, | 88 subresource_load_info_->request_id, subresource_load_info_->options, |
85 subresource_load_info_->request, std::move(client_info_), | 89 subresource_load_info_->request, std::move(client_ptr), |
86 subresource_load_info_->traffic_annotation); | 90 subresource_load_info_->traffic_annotation); |
87 } | 91 } |
88 } | 92 } |
89 | 93 |
90 void AppCacheURLLoaderJob::DeliverErrorResponse() { | 94 void AppCacheURLLoaderJob::DeliverErrorResponse() { |
91 delivery_type_ = ERROR_DELIVERY; | 95 delivery_type_ = ERROR_DELIVERY; |
92 | 96 |
93 // We expect the URLLoaderClient pointer to be valid at this point. | 97 // We expect the URLLoaderClient pointer to be valid at this point. |
94 DCHECK(client_info_); | 98 DCHECK(client_); |
95 | 99 |
96 // AppCacheURLRequestJob uses ERR_FAILED as the error code here. That seems | 100 // AppCacheURLRequestJob uses ERR_FAILED as the error code here. That seems |
97 // to map to HTTP_INTERNAL_SERVER_ERROR. | 101 // to map to HTTP_INTERNAL_SERVER_ERROR. |
98 std::string status("HTTP/1.1 "); | 102 std::string status("HTTP/1.1 "); |
99 status.append(base::IntToString(net::HTTP_INTERNAL_SERVER_ERROR)); | 103 status.append(base::IntToString(net::HTTP_INTERNAL_SERVER_ERROR)); |
100 status.append(" "); | 104 status.append(" "); |
101 status.append(net::GetHttpReasonPhrase(net::HTTP_INTERNAL_SERVER_ERROR)); | 105 status.append(net::GetHttpReasonPhrase(net::HTTP_INTERNAL_SERVER_ERROR)); |
102 status.append("\0\0", 2); | 106 status.append("\0\0", 2); |
103 | 107 |
104 ResourceResponseHead response; | 108 ResourceResponseHead response; |
105 response.headers = new net::HttpResponseHeaders(status); | 109 response.headers = new net::HttpResponseHeaders(status); |
106 client_info_->OnReceiveResponse(response, base::nullopt, nullptr); | 110 client_->OnReceiveResponse(response, base::nullopt, nullptr); |
107 | 111 |
108 NotifyCompleted(net::ERR_FAILED); | 112 NotifyCompleted(net::ERR_FAILED); |
109 | 113 |
110 AppCacheHistograms::AddErrorJobStartDelaySample(base::TimeTicks::Now() - | 114 AppCacheHistograms::AddErrorJobStartDelaySample(base::TimeTicks::Now() - |
111 start_time_tick_); | 115 start_time_tick_); |
112 } | 116 } |
113 | 117 |
114 const GURL& AppCacheURLLoaderJob::GetURL() const { | 118 const GURL& AppCacheURLLoaderJob::GetURL() const { |
115 return request_.url; | 119 return request_.url; |
116 } | 120 } |
117 | 121 |
118 AppCacheURLLoaderJob* AppCacheURLLoaderJob::AsURLLoaderJob() { | 122 AppCacheURLLoaderJob* AppCacheURLLoaderJob::AsURLLoaderJob() { |
119 return this; | 123 return this; |
120 } | 124 } |
121 | 125 |
122 void AppCacheURLLoaderJob::FollowRedirect() { | 126 void AppCacheURLLoaderJob::FollowRedirect() { |
123 if (network_loader_request_) | 127 if (network_loader_) |
124 network_loader_request_->FollowRedirect(); | 128 network_loader_->FollowRedirect(); |
125 } | 129 } |
126 | 130 |
127 void AppCacheURLLoaderJob::SetPriority(net::RequestPriority priority, | 131 void AppCacheURLLoaderJob::SetPriority(net::RequestPriority priority, |
128 int32_t intra_priority_value) { | 132 int32_t intra_priority_value) { |
129 if (network_loader_request_) | 133 if (network_loader_) |
130 network_loader_request_->SetPriority(priority, intra_priority_value); | 134 network_loader_->SetPriority(priority, intra_priority_value); |
| 135 } |
| 136 |
| 137 void AppCacheURLLoaderJob::OnReceiveResponse( |
| 138 const ResourceResponseHead& response_head, |
| 139 const base::Optional<net::SSLInfo>& ssl_info, |
| 140 mojom::DownloadedTempFilePtr downloaded_file) { |
| 141 appcache_request_->set_response(response_head); |
| 142 // The MaybeLoadFallbackForResponse() call below can pass a fallback |
| 143 // response to us. Reset the delivery_type_ to ensure that we can |
| 144 // receive it |
| 145 delivery_type_ = AWAITING_DELIVERY_ORDERS; |
| 146 if (!sub_resource_handler_->MaybeLoadFallbackForResponse(nullptr)) { |
| 147 client_->OnReceiveResponse(response_head, ssl_info, |
| 148 std::move(downloaded_file)); |
| 149 } else { |
| 150 // Disconnect from the network loader as we are delivering a fallback |
| 151 // response to the client. |
| 152 DisconnectFromNetworkLoader(); |
| 153 } |
| 154 } |
| 155 |
| 156 void AppCacheURLLoaderJob::OnReceiveRedirect( |
| 157 const net::RedirectInfo& redirect_info, |
| 158 const ResourceResponseHead& response_head) { |
| 159 appcache_request_->set_response(response_head); |
| 160 // The MaybeLoadFallbackForRedirect() call below can pass a fallback |
| 161 // response to us. Reset the delivery_type_ to ensure that we can |
| 162 // receive it |
| 163 delivery_type_ = AWAITING_DELIVERY_ORDERS; |
| 164 if (!sub_resource_handler_->MaybeLoadFallbackForRedirect( |
| 165 nullptr, redirect_info.new_url)) { |
| 166 client_->OnReceiveRedirect(redirect_info, response_head); |
| 167 } else { |
| 168 // Disconnect from the network loader as we are delivering a fallback |
| 169 // response to the client. |
| 170 DisconnectFromNetworkLoader(); |
| 171 } |
| 172 } |
| 173 |
| 174 void AppCacheURLLoaderJob::OnDataDownloaded(int64_t data_len, |
| 175 int64_t encoded_data_len) { |
| 176 client_->OnDataDownloaded(data_len, encoded_data_len); |
| 177 } |
| 178 |
| 179 void AppCacheURLLoaderJob::OnUploadProgress( |
| 180 int64_t current_position, |
| 181 int64_t total_size, |
| 182 OnUploadProgressCallback ack_callback) { |
| 183 client_->OnUploadProgress(current_position, total_size, |
| 184 std::move(ack_callback)); |
| 185 } |
| 186 |
| 187 void AppCacheURLLoaderJob::OnReceiveCachedMetadata( |
| 188 const std::vector<uint8_t>& data) { |
| 189 client_->OnReceiveCachedMetadata(data); |
| 190 } |
| 191 |
| 192 void AppCacheURLLoaderJob::OnTransferSizeUpdated(int32_t transfer_size_diff) { |
| 193 client_->OnTransferSizeUpdated(transfer_size_diff); |
| 194 } |
| 195 |
| 196 void AppCacheURLLoaderJob::OnStartLoadingResponseBody( |
| 197 mojo::ScopedDataPipeConsumerHandle body) { |
| 198 client_->OnStartLoadingResponseBody(std::move(body)); |
| 199 } |
| 200 |
| 201 void AppCacheURLLoaderJob::OnComplete( |
| 202 const ResourceRequestCompletionStatus& status) { |
| 203 delivery_type_ = AWAITING_DELIVERY_ORDERS; |
| 204 if (!sub_resource_handler_->MaybeLoadFallbackForResponse(nullptr)) { |
| 205 client_->OnComplete(status); |
| 206 } else { |
| 207 // Disconnect from the network loader as we are delivering a fallback |
| 208 // response to the client. |
| 209 DisconnectFromNetworkLoader(); |
| 210 } |
131 } | 211 } |
132 | 212 |
133 void AppCacheURLLoaderJob::SetSubresourceLoadInfo( | 213 void AppCacheURLLoaderJob::SetSubresourceLoadInfo( |
134 std::unique_ptr<SubresourceLoadInfo> subresource_load_info, | 214 std::unique_ptr<SubresourceLoadInfo> subresource_load_info, |
135 URLLoaderFactoryGetter* default_url_loader) { | 215 URLLoaderFactoryGetter* default_url_loader) { |
136 subresource_load_info_ = std::move(subresource_load_info); | 216 subresource_load_info_ = std::move(subresource_load_info); |
137 | 217 |
138 associated_binding_.reset(new mojo::AssociatedBinding<mojom::URLLoader>( | 218 associated_binding_.reset(new mojo::AssociatedBinding<mojom::URLLoader>( |
139 this, std::move(subresource_load_info_->url_loader_request))); | 219 this, std::move(subresource_load_info_->url_loader_request))); |
140 associated_binding_->set_connection_error_handler(base::Bind( | 220 associated_binding_->set_connection_error_handler(base::Bind( |
141 &AppCacheURLLoaderJob::OnConnectionError, StaticAsWeakPtr(this))); | 221 &AppCacheURLLoaderJob::OnConnectionError, StaticAsWeakPtr(this))); |
142 | 222 |
143 client_info_ = std::move(subresource_load_info_->client); | 223 client_ = std::move(subresource_load_info_->client); |
144 default_url_loader_factory_getter_ = default_url_loader; | 224 default_url_loader_factory_getter_ = default_url_loader; |
145 } | 225 } |
146 | 226 |
147 void AppCacheURLLoaderJob::Start(mojom::URLLoaderRequest request, | 227 void AppCacheURLLoaderJob::Start(mojom::URLLoaderRequest request, |
148 mojom::URLLoaderClientPtr client) { | 228 mojom::URLLoaderClientPtr client) { |
149 DCHECK(!binding_.is_bound()); | 229 DCHECK(!binding_.is_bound()); |
150 binding_.Bind(std::move(request)); | 230 binding_.Bind(std::move(request)); |
151 | 231 |
152 binding_.set_connection_error_handler(base::Bind( | 232 binding_.set_connection_error_handler(base::Bind( |
153 &AppCacheURLLoaderJob::OnConnectionError, StaticAsWeakPtr(this))); | 233 &AppCacheURLLoaderJob::OnConnectionError, StaticAsWeakPtr(this))); |
154 | 234 |
155 client_info_ = std::move(client); | 235 client_ = std::move(client); |
156 | 236 |
157 // Send the cached AppCacheResponse if any. | 237 // Send the cached AppCacheResponse if any. |
158 if (info_.get()) | 238 if (info_.get()) |
159 SendResponseInfo(); | 239 SendResponseInfo(); |
160 } | 240 } |
161 | 241 |
162 AppCacheURLLoaderJob::AppCacheURLLoaderJob(const ResourceRequest& request, | 242 AppCacheURLLoaderJob::AppCacheURLLoaderJob( |
163 AppCacheStorage* storage) | 243 const ResourceRequest& request, |
| 244 AppCacheURLLoaderRequest* appcache_request, |
| 245 AppCacheStorage* storage) |
164 : request_(request), | 246 : request_(request), |
165 storage_(storage->GetWeakPtr()), | 247 storage_(storage->GetWeakPtr()), |
166 start_time_tick_(base::TimeTicks::Now()), | 248 start_time_tick_(base::TimeTicks::Now()), |
167 cache_id_(kAppCacheNoCacheId), | 249 cache_id_(kAppCacheNoCacheId), |
168 is_fallback_(false), | 250 is_fallback_(false), |
169 binding_(this), | 251 binding_(this), |
170 writable_handle_watcher_(FROM_HERE, | 252 writable_handle_watcher_(FROM_HERE, |
171 mojo::SimpleWatcher::ArmingPolicy::MANUAL) {} | 253 mojo::SimpleWatcher::ArmingPolicy::MANUAL), |
| 254 network_loader_client_binding_(this), |
| 255 appcache_request_(appcache_request) {} |
172 | 256 |
173 void AppCacheURLLoaderJob::OnResponseInfoLoaded( | 257 void AppCacheURLLoaderJob::OnResponseInfoLoaded( |
174 AppCacheResponseInfo* response_info, | 258 AppCacheResponseInfo* response_info, |
175 int64_t response_id) { | 259 int64_t response_id) { |
176 DCHECK(IsDeliveringAppCacheResponse()); | 260 DCHECK(IsDeliveringAppCacheResponse()); |
177 | 261 |
178 if (!storage_.get()) { | 262 if (!storage_.get()) { |
179 DeliverErrorResponse(); | 263 DeliverErrorResponse(); |
180 return; | 264 return; |
181 } | 265 } |
(...skipping 17 matching lines...) Expand all Loading... |
199 // TODO(ananta) | 283 // TODO(ananta) |
200 // Move the asynchronous reading and mojo pipe handling code to a helper | 284 // Move the asynchronous reading and mojo pipe handling code to a helper |
201 // class. That would also need a change to BlobURLLoader. | 285 // class. That would also need a change to BlobURLLoader. |
202 | 286 |
203 // Wait for the data pipe to be ready to accept data. | 287 // Wait for the data pipe to be ready to accept data. |
204 writable_handle_watcher_.Watch( | 288 writable_handle_watcher_.Watch( |
205 response_body_stream_.get(), MOJO_HANDLE_SIGNAL_WRITABLE, | 289 response_body_stream_.get(), MOJO_HANDLE_SIGNAL_WRITABLE, |
206 base::Bind(&AppCacheURLLoaderJob::OnResponseBodyStreamReady, | 290 base::Bind(&AppCacheURLLoaderJob::OnResponseBodyStreamReady, |
207 StaticAsWeakPtr(this))); | 291 StaticAsWeakPtr(this))); |
208 | 292 |
209 if (client_info_) | 293 if (client_) |
210 SendResponseInfo(); | 294 SendResponseInfo(); |
211 | 295 |
212 ReadMore(); | 296 ReadMore(); |
213 } else { | 297 } else { |
214 // Error case here. We fallback to the network. | 298 // Error case here. We fallback to the network. |
215 DeliverNetworkResponse(); | 299 DeliverNetworkResponse(); |
216 AppCacheHistograms::CountResponseRetrieval( | 300 AppCacheHistograms::CountResponseRetrieval( |
217 false, IsResourceTypeFrame(request_.resource_type), | 301 false, IsResourceTypeFrame(request_.resource_type), |
218 manifest_url_.GetOrigin()); | 302 manifest_url_.GetOrigin()); |
219 | 303 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 ReadMore(); | 337 ReadMore(); |
254 } | 338 } |
255 | 339 |
256 void AppCacheURLLoaderJob::OnConnectionError() { | 340 void AppCacheURLLoaderJob::OnConnectionError() { |
257 if (storage_.get()) | 341 if (storage_.get()) |
258 storage_->CancelDelegateCallbacks(this); | 342 storage_->CancelDelegateCallbacks(this); |
259 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); | 343 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); |
260 } | 344 } |
261 | 345 |
262 void AppCacheURLLoaderJob::SendResponseInfo() { | 346 void AppCacheURLLoaderJob::SendResponseInfo() { |
263 DCHECK(client_info_); | 347 DCHECK(client_); |
264 // If this is null it means the response information was sent to the client. | 348 // If this is null it means the response information was sent to the client. |
265 if (!data_pipe_.consumer_handle.is_valid()) | 349 if (!data_pipe_.consumer_handle.is_valid()) |
266 return; | 350 return; |
267 | 351 |
268 const net::HttpResponseInfo* http_info = is_range_request() | 352 const net::HttpResponseInfo* http_info = is_range_request() |
269 ? range_response_info_.get() | 353 ? range_response_info_.get() |
270 : info_->http_response_info(); | 354 : info_->http_response_info(); |
271 | 355 |
272 ResourceResponseHead response_head; | 356 ResourceResponseHead response_head; |
273 response_head.headers = http_info->headers; | 357 response_head.headers = http_info->headers; |
(...skipping 12 matching lines...) Expand all Loading... |
286 : info_->response_data_size(); | 370 : info_->response_data_size(); |
287 | 371 |
288 response_head.connection_info = http_info->connection_info; | 372 response_head.connection_info = http_info->connection_info; |
289 response_head.socket_address = http_info->socket_address; | 373 response_head.socket_address = http_info->socket_address; |
290 response_head.was_fetched_via_spdy = http_info->was_fetched_via_spdy; | 374 response_head.was_fetched_via_spdy = http_info->was_fetched_via_spdy; |
291 response_head.was_alpn_negotiated = http_info->was_alpn_negotiated; | 375 response_head.was_alpn_negotiated = http_info->was_alpn_negotiated; |
292 response_head.alpn_negotiated_protocol = http_info->alpn_negotiated_protocol; | 376 response_head.alpn_negotiated_protocol = http_info->alpn_negotiated_protocol; |
293 | 377 |
294 response_head.load_timing = load_timing_info_; | 378 response_head.load_timing = load_timing_info_; |
295 | 379 |
296 client_info_->OnReceiveResponse(response_head, http_info->ssl_info, | 380 appcache_request_->set_response(response_head); |
297 mojom::DownloadedTempFilePtr()); | |
298 | 381 |
299 client_info_->OnStartLoadingResponseBody( | 382 client_->OnReceiveResponse(response_head, http_info->ssl_info, |
300 std::move(data_pipe_.consumer_handle)); | 383 mojom::DownloadedTempFilePtr()); |
| 384 |
| 385 client_->OnStartLoadingResponseBody(std::move(data_pipe_.consumer_handle)); |
301 } | 386 } |
302 | 387 |
303 void AppCacheURLLoaderJob::ReadMore() { | 388 void AppCacheURLLoaderJob::ReadMore() { |
304 DCHECK(!pending_write_.get()); | 389 DCHECK(!pending_write_.get()); |
305 | 390 |
306 uint32_t num_bytes; | 391 uint32_t num_bytes; |
307 // TODO: we should use the abstractions in MojoAsyncResourceHandler. | 392 // TODO: we should use the abstractions in MojoAsyncResourceHandler. |
308 MojoResult result = NetToMojoPendingBuffer::BeginWrite( | 393 MojoResult result = NetToMojoPendingBuffer::BeginWrite( |
309 &response_body_stream_, &pending_write_, &num_bytes); | 394 &response_body_stream_, &pending_write_, &num_bytes); |
310 if (result == MOJO_RESULT_SHOULD_WAIT) { | 395 if (result == MOJO_RESULT_SHOULD_WAIT) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 // case of an error. | 441 // case of an error. |
357 if (!request_complete_data.error_code) { | 442 if (!request_complete_data.error_code) { |
358 request_complete_data.exists_in_cache = http_info->was_cached; | 443 request_complete_data.exists_in_cache = http_info->was_cached; |
359 request_complete_data.completion_time = base::TimeTicks::Now(); | 444 request_complete_data.completion_time = base::TimeTicks::Now(); |
360 request_complete_data.encoded_body_length = | 445 request_complete_data.encoded_body_length = |
361 is_range_request() ? range_response_info_->headers->GetContentLength() | 446 is_range_request() ? range_response_info_->headers->GetContentLength() |
362 : info_->response_data_size(); | 447 : info_->response_data_size(); |
363 request_complete_data.decoded_body_length = | 448 request_complete_data.decoded_body_length = |
364 request_complete_data.encoded_body_length; | 449 request_complete_data.encoded_body_length; |
365 } | 450 } |
366 client_info_->OnComplete(request_complete_data); | 451 client_->OnComplete(request_complete_data); |
| 452 } |
| 453 |
| 454 void AppCacheURLLoaderJob::DisconnectFromNetworkLoader() { |
| 455 // Close the pipe to the network loader as we are delivering a fallback |
| 456 // response to the client. |
| 457 network_loader_client_binding_.Close(); |
| 458 network_loader_ = nullptr; |
367 } | 459 } |
368 | 460 |
369 } // namespace content | 461 } // namespace content |
OLD | NEW |