| 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" |
| 10 #include "content/browser/url_loader_factory_getter.h" |
| 9 #include "content/common/net_adapters.h" | 11 #include "content/common/net_adapters.h" |
| 10 #include "content/public/common/resource_type.h" | 12 #include "content/public/common/resource_type.h" |
| 11 #include "net/http/http_status_code.h" | 13 #include "net/http/http_status_code.h" |
| 12 | 14 |
| 13 namespace content { | 15 namespace content { |
| 14 | 16 |
| 15 AppCacheURLLoaderJob::~AppCacheURLLoaderJob() { | 17 AppCacheURLLoaderJob::~AppCacheURLLoaderJob() { |
| 16 if (storage_.get()) | 18 if (storage_.get()) |
| 17 storage_->CancelDelegateCallbacks(this); | 19 storage_->CancelDelegateCallbacks(this); |
| 18 } | 20 } |
| 19 | 21 |
| 20 void AppCacheURLLoaderJob::Kill() {} | 22 void AppCacheURLLoaderJob::Kill() {} |
| 21 | 23 |
| 22 bool AppCacheURLLoaderJob::IsStarted() const { | 24 bool AppCacheURLLoaderJob::IsStarted() const { |
| 23 return delivery_type_ != AWAITING_DELIVERY_ORDERS; | 25 return delivery_type_ != AWAITING_DELIVERY_ORDERS; |
| 24 } | 26 } |
| 25 | 27 |
| 26 void AppCacheURLLoaderJob::DeliverAppCachedResponse(const GURL& manifest_url, | 28 void AppCacheURLLoaderJob::DeliverAppCachedResponse(const GURL& manifest_url, |
| 27 int64_t cache_id, | 29 int64_t cache_id, |
| 28 const AppCacheEntry& entry, | 30 const AppCacheEntry& entry, |
| 29 bool is_fallback) { | 31 bool is_fallback) { |
| 30 if (!storage_.get()) { | 32 if (!storage_.get()) { |
| 31 DeliverErrorResponse(); | 33 DeliverErrorResponse(); |
| 32 return; | 34 return; |
| 33 } | 35 } |
| 34 | 36 |
| 35 delivery_type_ = APPCACHED_DELIVERY; | 37 delivery_type_ = APPCACHED_DELIVERY; |
| 36 | 38 |
| 39 load_timing_info_.request_start_time = base::Time::Now(); |
| 40 load_timing_info_.request_start = base::TimeTicks::Now(); |
| 41 |
| 37 AppCacheHistograms::AddAppCacheJobStartDelaySample(base::TimeTicks::Now() - | 42 AppCacheHistograms::AddAppCacheJobStartDelaySample(base::TimeTicks::Now() - |
| 38 start_time_tick_); | 43 start_time_tick_); |
| 39 | 44 |
| 40 manifest_url_ = manifest_url; | 45 manifest_url_ = manifest_url; |
| 41 cache_id_ = cache_id; | 46 cache_id_ = cache_id; |
| 42 entry_ = entry; | 47 entry_ = entry; |
| 43 is_fallback_ = is_fallback; | 48 is_fallback_ = is_fallback; |
| 44 | 49 |
| 45 // Handle range requests. | 50 // Handle range requests. |
| 46 net::HttpRequestHeaders headers; | 51 net::HttpRequestHeaders headers; |
| 47 headers.AddHeadersFromString(request_.headers); | 52 headers.AddHeadersFromString(request_.headers); |
| 48 InitializeRangeRequestInfo(headers); | 53 InitializeRangeRequestInfo(headers); |
| 49 | 54 |
| 50 // TODO(ananta) | 55 // TODO(ananta) |
| 51 // Implement the AppCacheServiceImpl::Observer interface or add weak pointer | 56 // Implement the AppCacheServiceImpl::Observer interface or add weak pointer |
| 52 // support to it. | 57 // support to it. |
| 53 storage_->LoadResponseInfo(manifest_url_, entry_.response_id(), this); | 58 storage_->LoadResponseInfo(manifest_url_, entry_.response_id(), this); |
| 54 } | 59 } |
| 55 | 60 |
| 56 void AppCacheURLLoaderJob::DeliverNetworkResponse() { | 61 void AppCacheURLLoaderJob::DeliverNetworkResponse() { |
| 57 delivery_type_ = NETWORK_DELIVERY; | 62 delivery_type_ = NETWORK_DELIVERY; |
| 58 | 63 |
| 59 AppCacheHistograms::AddNetworkJobStartDelaySample(base::TimeTicks::Now() - | 64 AppCacheHistograms::AddNetworkJobStartDelaySample(base::TimeTicks::Now() - |
| 60 start_time_tick_); | 65 start_time_tick_); |
| 61 | 66 |
| 62 DCHECK(!loader_callback_.is_null()); | 67 if (IsResourceTypeFrame(request_.resource_type)) { |
| 63 // In network service land, if we are processing a navigation request, we | 68 DCHECK(!loader_callback_.is_null()); |
| 64 // need to inform the loader callback that we are not going to handle this | 69 // In network service land, if we are processing a navigation request, we |
| 65 // request. The loader callback is valid only for navigation requests. | 70 // need to inform the loader callback that we are not going to handle this |
| 66 std::move(loader_callback_).Run(StartLoaderCallback()); | 71 // request. The loader callback is valid only for navigation requests. |
| 72 std::move(loader_callback_).Run(StartLoaderCallback()); |
| 73 } else { |
| 74 default_url_loader_factory_getter_->GetNetworkFactory() |
| 75 ->get() |
| 76 ->CreateLoaderAndStart( |
| 77 mojo::MakeRequest(&network_loader_request_), |
| 78 subresource_load_info_->routing_id, |
| 79 subresource_load_info_->request_id, subresource_load_info_->options, |
| 80 subresource_load_info_->request, std::move(client_info_), |
| 81 subresource_load_info_->traffic_annotation); |
| 82 } |
| 67 } | 83 } |
| 68 | 84 |
| 69 void AppCacheURLLoaderJob::DeliverErrorResponse() { | 85 void AppCacheURLLoaderJob::DeliverErrorResponse() { |
| 70 delivery_type_ = ERROR_DELIVERY; | 86 delivery_type_ = ERROR_DELIVERY; |
| 71 | 87 |
| 72 // We expect the URLLoaderClient pointer to be valid at this point. | 88 // We expect the URLLoaderClient pointer to be valid at this point. |
| 73 DCHECK(client_info_); | 89 DCHECK(client_info_); |
| 74 | 90 |
| 75 // AppCacheURLRequestJob uses ERR_FAILED as the error code here. That seems | 91 // AppCacheURLRequestJob uses ERR_FAILED as the error code here. That seems |
| 76 // to map to HTTP_INTERNAL_SERVER_ERROR. | 92 // to map to HTTP_INTERNAL_SERVER_ERROR. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 92 | 108 |
| 93 const GURL& AppCacheURLLoaderJob::GetURL() const { | 109 const GURL& AppCacheURLLoaderJob::GetURL() const { |
| 94 return request_.url; | 110 return request_.url; |
| 95 } | 111 } |
| 96 | 112 |
| 97 AppCacheURLLoaderJob* AppCacheURLLoaderJob::AsURLLoaderJob() { | 113 AppCacheURLLoaderJob* AppCacheURLLoaderJob::AsURLLoaderJob() { |
| 98 return this; | 114 return this; |
| 99 } | 115 } |
| 100 | 116 |
| 101 void AppCacheURLLoaderJob::FollowRedirect() { | 117 void AppCacheURLLoaderJob::FollowRedirect() { |
| 102 DCHECK(false); | 118 if (network_loader_request_) |
| 119 network_loader_request_->FollowRedirect(); |
| 103 } | 120 } |
| 104 | 121 |
| 105 void AppCacheURLLoaderJob::SetPriority(net::RequestPriority priority, | 122 void AppCacheURLLoaderJob::SetPriority(net::RequestPriority priority, |
| 106 int32_t intra_priority_value) { | 123 int32_t intra_priority_value) { |
| 107 NOTREACHED() << "We don't support SetPriority()"; | 124 if (network_loader_request_) |
| 125 network_loader_request_->SetPriority(priority, intra_priority_value); |
| 126 } |
| 127 |
| 128 void AppCacheURLLoaderJob::SetSubresourceLoadInfo( |
| 129 std::unique_ptr<SubresourceLoadInfo> subresource_load_info, |
| 130 AppCacheRequestHandler* handler, |
| 131 URLLoaderFactoryGetter* default_url_loader) { |
| 132 subresource_load_info_ = std::move(subresource_load_info); |
| 133 |
| 134 associated_binding_.reset(new mojo::AssociatedBinding<mojom::URLLoader>( |
| 135 this, std::move(subresource_load_info_->url_loader_request))); |
| 136 associated_binding_->set_connection_error_handler(base::Bind( |
| 137 &AppCacheURLLoaderJob::OnConnectionError, StaticAsWeakPtr(this))); |
| 138 |
| 139 client_info_ = std::move(subresource_load_info_->client); |
| 140 |
| 141 handler_.reset(handler); |
| 142 default_url_loader_factory_getter_ = default_url_loader; |
| 108 } | 143 } |
| 109 | 144 |
| 110 void AppCacheURLLoaderJob::Start(mojom::URLLoaderRequest request, | 145 void AppCacheURLLoaderJob::Start(mojom::URLLoaderRequest request, |
| 111 mojom::URLLoaderClientPtr client) { | 146 mojom::URLLoaderClientPtr client) { |
| 112 DCHECK(!binding_.is_bound()); | 147 DCHECK(!binding_.is_bound()); |
| 113 binding_.Bind(std::move(request)); | 148 binding_.Bind(std::move(request)); |
| 114 | 149 |
| 115 binding_.set_connection_error_handler(base::Bind( | 150 binding_.set_connection_error_handler(base::Bind( |
| 116 &AppCacheURLLoaderJob::OnConnectionError, StaticAsWeakPtr(this))); | 151 &AppCacheURLLoaderJob::OnConnectionError, StaticAsWeakPtr(this))); |
| 117 | 152 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 144 } | 179 } |
| 145 | 180 |
| 146 if (response_info) { | 181 if (response_info) { |
| 147 info_ = response_info; | 182 info_ = response_info; |
| 148 reader_.reset( | 183 reader_.reset( |
| 149 storage_->CreateResponseReader(manifest_url_, entry_.response_id())); | 184 storage_->CreateResponseReader(manifest_url_, entry_.response_id())); |
| 150 | 185 |
| 151 if (is_range_request()) | 186 if (is_range_request()) |
| 152 SetupRangeResponse(); | 187 SetupRangeResponse(); |
| 153 | 188 |
| 154 DCHECK(!loader_callback_.is_null()); | 189 if (IsResourceTypeFrame(request_.resource_type)) { |
| 155 std::move(loader_callback_) | 190 DCHECK(!loader_callback_.is_null()); |
| 156 .Run(base::Bind(&AppCacheURLLoaderJob::Start, StaticAsWeakPtr(this))); | 191 std::move(loader_callback_) |
| 192 .Run(base::Bind(&AppCacheURLLoaderJob::Start, StaticAsWeakPtr(this))); |
| 193 } |
| 157 | 194 |
| 158 response_body_stream_ = std::move(data_pipe_.producer_handle); | 195 response_body_stream_ = std::move(data_pipe_.producer_handle); |
| 159 | 196 |
| 160 // TODO(ananta) | 197 // TODO(ananta) |
| 161 // Move the asynchronous reading and mojo pipe handling code to a helper | 198 // Move the asynchronous reading and mojo pipe handling code to a helper |
| 162 // class. That would also need a change to BlobURLLoader. | 199 // class. That would also need a change to BlobURLLoader. |
| 163 | 200 |
| 164 // Wait for the data pipe to be ready to accept data. | 201 // Wait for the data pipe to be ready to accept data. |
| 165 writable_handle_watcher_.Watch( | 202 writable_handle_watcher_.Watch( |
| 166 response_body_stream_.get(), MOJO_HANDLE_SIGNAL_WRITABLE, | 203 response_body_stream_.get(), MOJO_HANDLE_SIGNAL_WRITABLE, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 178 false, IsResourceTypeFrame(request_.resource_type), | 215 false, IsResourceTypeFrame(request_.resource_type), |
| 179 manifest_url_.GetOrigin()); | 216 manifest_url_.GetOrigin()); |
| 180 | 217 |
| 181 cache_entry_not_found_ = true; | 218 cache_entry_not_found_ = true; |
| 182 } | 219 } |
| 183 } | 220 } |
| 184 | 221 |
| 185 void AppCacheURLLoaderJob::OnReadComplete(int result) { | 222 void AppCacheURLLoaderJob::OnReadComplete(int result) { |
| 186 DLOG(WARNING) << "AppCache read completed with result: " << result; | 223 DLOG(WARNING) << "AppCache read completed with result: " << result; |
| 187 | 224 |
| 225 if (result <= 0) { |
| 226 writable_handle_watcher_.Cancel(); |
| 227 pending_write_->Complete(0); |
| 228 pending_write_ = nullptr; |
| 229 } |
| 230 |
| 188 bool is_main_resource = IsResourceTypeFrame(request_.resource_type); | 231 bool is_main_resource = IsResourceTypeFrame(request_.resource_type); |
| 189 | 232 |
| 190 if (result == 0) { | 233 if (result == 0) { |
| 191 NotifyCompleted(result); | 234 NotifyCompleted(result); |
| 192 AppCacheHistograms::CountResponseRetrieval(true, is_main_resource, | 235 AppCacheHistograms::CountResponseRetrieval(true, is_main_resource, |
| 193 manifest_url_.GetOrigin()); | 236 manifest_url_.GetOrigin()); |
| 194 return; | 237 return; |
| 195 } else if (result < 0) { | 238 } else if (result < 0) { |
| 196 // TODO(ananta) | 239 // TODO(ananta) |
| 197 // Populate the relevant fields of the ResourceRequestCompletionStatus | 240 // Populate the relevant fields of the ResourceRequestCompletionStatus |
| (...skipping 11 matching lines...) Expand all Loading... |
| 209 } | 252 } |
| 210 | 253 |
| 211 void AppCacheURLLoaderJob::OnConnectionError() { | 254 void AppCacheURLLoaderJob::OnConnectionError() { |
| 212 if (storage_.get()) | 255 if (storage_.get()) |
| 213 storage_->CancelDelegateCallbacks(this); | 256 storage_->CancelDelegateCallbacks(this); |
| 214 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); | 257 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); |
| 215 } | 258 } |
| 216 | 259 |
| 217 void AppCacheURLLoaderJob::SendResponseInfo() { | 260 void AppCacheURLLoaderJob::SendResponseInfo() { |
| 218 DCHECK(client_info_); | 261 DCHECK(client_info_); |
| 219 | |
| 220 // If this is null it means the response information was sent to the client. | 262 // If this is null it means the response information was sent to the client. |
| 221 if (!data_pipe_.consumer_handle.is_valid()) | 263 if (!data_pipe_.consumer_handle.is_valid()) |
| 222 return; | 264 return; |
| 223 | 265 |
| 224 const net::HttpResponseInfo* http_info = is_range_request() | 266 const net::HttpResponseInfo* http_info = is_range_request() |
| 225 ? range_response_info_.get() | 267 ? range_response_info_.get() |
| 226 : info_->http_response_info(); | 268 : info_->http_response_info(); |
| 227 | 269 |
| 228 ResourceResponseHead response_head; | 270 ResourceResponseHead response_head; |
| 229 response_head.headers = http_info->headers; | 271 response_head.headers = http_info->headers; |
| 272 response_head.appcache_id = cache_id_; |
| 273 response_head.appcache_manifest_url = manifest_url_; |
| 230 | 274 |
| 231 // TODO(ananta) | |
| 232 // Copy more fields. | |
| 233 http_info->headers->GetMimeType(&response_head.mime_type); | 275 http_info->headers->GetMimeType(&response_head.mime_type); |
| 234 http_info->headers->GetCharset(&response_head.charset); | 276 http_info->headers->GetCharset(&response_head.charset); |
| 235 | 277 |
| 278 // TODO(ananta) |
| 279 // Verify if the times sent here are correct. |
| 236 response_head.request_time = http_info->request_time; | 280 response_head.request_time = http_info->request_time; |
| 237 response_head.response_time = http_info->response_time; | 281 response_head.response_time = http_info->response_time; |
| 238 response_head.content_length = | 282 response_head.content_length = |
| 239 is_range_request() ? range_response_info_->headers->GetContentLength() | 283 is_range_request() ? range_response_info_->headers->GetContentLength() |
| 240 : info_->response_data_size(); | 284 : info_->response_data_size(); |
| 241 | 285 |
| 286 response_head.connection_info = http_info->connection_info; |
| 287 response_head.socket_address = http_info->socket_address; |
| 288 response_head.was_fetched_via_spdy = http_info->was_fetched_via_spdy; |
| 289 response_head.was_alpn_negotiated = http_info->was_alpn_negotiated; |
| 290 response_head.alpn_negotiated_protocol = http_info->alpn_negotiated_protocol; |
| 291 |
| 292 response_head.load_timing = load_timing_info_; |
| 293 |
| 242 client_info_->OnReceiveResponse(response_head, http_info->ssl_info, | 294 client_info_->OnReceiveResponse(response_head, http_info->ssl_info, |
| 243 mojom::DownloadedTempFilePtr()); | 295 mojom::DownloadedTempFilePtr()); |
| 244 | 296 |
| 245 client_info_->OnStartLoadingResponseBody( | 297 client_info_->OnStartLoadingResponseBody( |
| 246 std::move(data_pipe_.consumer_handle)); | 298 std::move(data_pipe_.consumer_handle)); |
| 247 } | 299 } |
| 248 | 300 |
| 249 void AppCacheURLLoaderJob::ReadMore() { | 301 void AppCacheURLLoaderJob::ReadMore() { |
| 250 DCHECK(!pending_write_.get()); | 302 DCHECK(!pending_write_.get()); |
| 251 | 303 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 282 if (result != MOJO_RESULT_OK) { | 334 if (result != MOJO_RESULT_OK) { |
| 283 DCHECK(false); | 335 DCHECK(false); |
| 284 NotifyCompleted(net::ERR_FAILED); | 336 NotifyCompleted(net::ERR_FAILED); |
| 285 } | 337 } |
| 286 ReadMore(); | 338 ReadMore(); |
| 287 } | 339 } |
| 288 | 340 |
| 289 void AppCacheURLLoaderJob::NotifyCompleted(int error_code) { | 341 void AppCacheURLLoaderJob::NotifyCompleted(int error_code) { |
| 290 if (storage_.get()) | 342 if (storage_.get()) |
| 291 storage_->CancelDelegateCallbacks(this); | 343 storage_->CancelDelegateCallbacks(this); |
| 292 // TODO(ananta) | 344 |
| 293 // Fill other details in the ResourceRequestCompletionStatus structure. | 345 const net::HttpResponseInfo* http_info = is_range_request() |
| 346 ? range_response_info_.get() |
| 347 : info_->http_response_info(); |
| 348 |
| 294 ResourceRequestCompletionStatus request_complete_data; | 349 ResourceRequestCompletionStatus request_complete_data; |
| 295 request_complete_data.error_code = error_code; | 350 request_complete_data.error_code = error_code; |
| 351 |
| 352 // TODO(ananta) |
| 353 // Fill other details in the ResourceRequestCompletionStatus structure in |
| 354 // case of an error. |
| 355 if (!request_complete_data.error_code) { |
| 356 request_complete_data.exists_in_cache = http_info->was_cached; |
| 357 request_complete_data.completion_time = base::TimeTicks::Now(); |
| 358 request_complete_data.encoded_body_length = |
| 359 is_range_request() ? range_response_info_->headers->GetContentLength() |
| 360 : info_->response_data_size(); |
| 361 request_complete_data.decoded_body_length = |
| 362 request_complete_data.encoded_body_length; |
| 363 } |
| 296 client_info_->OnComplete(request_complete_data); | 364 client_info_->OnComplete(request_complete_data); |
| 297 } | 365 } |
| 298 | 366 |
| 299 } // namespace content | 367 } // namespace content |
| OLD | NEW |