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