Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(97)

Side by Side Diff: content/browser/appcache/appcache_url_loader_job.cc

Issue 2902653002: Get main frame and subframe AppCache loads to work. (Closed)
Patch Set: Add weakptr support to AppCacheStorage and provide a way to return the weakptr. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #include "content/browser/appcache/appcache_entry.h" 6
7 #include "base/strings/string_number_conversions.h"
8 #include "content/browser/appcache/appcache_histograms.h"
9 #include "content/common/net_adapters.h"
10 #include "content/public/common/resource_type.h"
11 #include "net/http/http_status_code.h"
7 12
8 namespace content { 13 namespace content {
9 14
10 AppCacheURLLoaderJob::~AppCacheURLLoaderJob() {} 15 AppCacheURLLoaderJob::~AppCacheURLLoaderJob() {
16 if (storage_.get())
17 storage_->CancelDelegateCallbacks(this);
18 }
11 19
12 void AppCacheURLLoaderJob::Kill() {} 20 void AppCacheURLLoaderJob::Kill() {}
13 21
14 bool AppCacheURLLoaderJob::IsStarted() const { 22 bool AppCacheURLLoaderJob::IsStarted() const {
15 return false; 23 return delivery_type_ != AWAITING_DELIVERY_ORDERS;
16 }
17
18 bool AppCacheURLLoaderJob::IsWaiting() const {
19 return false;
20 }
21
22 bool AppCacheURLLoaderJob::IsDeliveringAppCacheResponse() const {
23 return false;
24 }
25
26 bool AppCacheURLLoaderJob::IsDeliveringNetworkResponse() const {
27 return false;
28 }
29
30 bool AppCacheURLLoaderJob::IsDeliveringErrorResponse() const {
31 return false;
32 }
33
34 bool AppCacheURLLoaderJob::IsCacheEntryNotFound() const {
35 return false;
36 } 24 }
37 25
38 void AppCacheURLLoaderJob::DeliverAppCachedResponse(const GURL& manifest_url, 26 void AppCacheURLLoaderJob::DeliverAppCachedResponse(const GURL& manifest_url,
39 int64_t cache_id, 27 int64_t cache_id,
40 const AppCacheEntry& entry, 28 const AppCacheEntry& entry,
41 bool is_fallback) {} 29 bool is_fallback) {
42 30 // Should we send out an error response here?. We may not have a client
43 void AppCacheURLLoaderJob::DeliverNetworkResponse() {} 31 // connection at this point though.
michaeln 2017/06/09 21:49:00 probably we should call DeliverErrorResponse() her
ananta 2017/06/09 22:16:52 Done.
44 32 if (!storage_.get())
45 void AppCacheURLLoaderJob::DeliverErrorResponse() {} 33 return;
34
35 delivery_type_ = APPCACHED_DELIVERY;
36
37 AppCacheHistograms::AddAppCacheJobStartDelaySample(base::TimeTicks::Now() -
38 start_time_tick_);
39
40 manifest_url_ = manifest_url;
41 cache_id_ = cache_id;
42 entry_ = entry;
43 is_fallback_ = is_fallback;
44
45 // TODO(ananta)
46 // Implement the AppCacheServiceImpl::Observer interface or add weak pointer
47 // support to it.
48 storage_->LoadResponseInfo(manifest_url_, entry_.response_id(), this);
49 }
50
51 void AppCacheURLLoaderJob::DeliverNetworkResponse() {
52 delivery_type_ = NETWORK_DELIVERY;
53
54 AppCacheHistograms::AddNetworkJobStartDelaySample(base::TimeTicks::Now() -
55 start_time_tick_);
56
57 DCHECK(!loader_callback_.is_null());
58 // In network service land, if we are processing a navigation request, we
59 // need to inform the loader callback that we are not going to handle this
60 // request. The loader callback is valid only for navigation requests.
61 std::move(loader_callback_).Run(StartLoaderCallback());
62 }
63
64 void AppCacheURLLoaderJob::DeliverErrorResponse() {
65 delivery_type_ = ERROR_DELIVERY;
66
67 // We expect the URLLoaderClient pointer to be valid at this point.
68 DCHECK(client_info_);
69
70 // AppCacheURLRequestJob uses ERR_FAILED as the error code here. That seems
71 // to map to HTTP_INTERNAL_SERVER_ERROR.
72 std::string status("HTTP/1.1 ");
73 status.append(base::IntToString(net::HTTP_INTERNAL_SERVER_ERROR));
74 status.append(" ");
75 status.append(net::GetHttpReasonPhrase(net::HTTP_INTERNAL_SERVER_ERROR));
76 status.append("\0\0", 2);
77
78 ResourceResponseHead response;
79 response.headers = new net::HttpResponseHeaders(status);
80 client_info_->OnReceiveResponse(response, base::nullopt, nullptr);
81
82 NotifyCompleted(net::ERR_FAILED);
83
84 AppCacheHistograms::AddErrorJobStartDelaySample(base::TimeTicks::Now() -
85 start_time_tick_);
86 }
46 87
47 const GURL& AppCacheURLLoaderJob::GetURL() const { 88 const GURL& AppCacheURLLoaderJob::GetURL() const {
48 return url_; 89 return request_.url;
49 } 90 }
50 91
51 AppCacheURLLoaderJob::AppCacheURLLoaderJob() {} 92 AppCacheURLLoaderJob* AppCacheURLLoaderJob::AsURLLoaderJob() {
93 return this;
94 }
95
96 void AppCacheURLLoaderJob::FollowRedirect() {
97 DCHECK(false);
98 }
99
100 void AppCacheURLLoaderJob::SetPriority(net::RequestPriority priority,
101 int32_t intra_priority_value) {
102 NOTREACHED() << "We don't support SetPriority()";
103 }
104
105 void AppCacheURLLoaderJob::Start(mojom::URLLoaderRequest request,
106 mojom::URLLoaderClientPtr client) {
107 DCHECK(!binding_.is_bound());
108 binding_.Bind(std::move(request));
109
110 binding_.set_connection_error_handler(base::Bind(
111 &AppCacheURLLoaderJob::OnConnectionError, StaticAsWeakPtr(this)));
112
113 client_info_ = std::move(client);
114
115 // Send the cached AppCacheResponse if any.
116 if (info_.get())
117 SendResponseInfo();
118 }
119
120 AppCacheURLLoaderJob::AppCacheURLLoaderJob(const ResourceRequest& request,
121 AppCacheStorage* storage)
122 : request_(request),
123 storage_(storage->GetWeakPtr()),
124 start_time_tick_(base::TimeTicks::Now()),
125 cache_id_(kAppCacheNoCacheId),
126 is_fallback_(false),
127 binding_(this),
128 writable_handle_watcher_(FROM_HERE,
129 mojo::SimpleWatcher::ArmingPolicy::MANUAL) {}
130
131 void AppCacheURLLoaderJob::OnResponseInfoLoaded(
132 AppCacheResponseInfo* response_info,
133 int64_t response_id) {
134 DCHECK(IsDeliveringAppCacheResponse());
135
136 if (!storage_.get()) {
137 NotifyCompleted(net::ERR_FAILED);
michaeln 2017/06/09 21:49:00 at this point, we haven't sent headers yet, we can
ananta 2017/06/09 22:16:52 Done.
138 return;
139 }
140
141 if (response_info) {
142 info_ = response_info;
143 reader_.reset(
144 storage_->CreateResponseReader(manifest_url_, entry_.response_id()));
145
146 DCHECK(!loader_callback_.is_null());
147 std::move(loader_callback_)
148 .Run(base::Bind(&AppCacheURLLoaderJob::Start, StaticAsWeakPtr(this)));
149
150 // TODO(ananta)
151 // Handle range requests.
152
153 response_body_stream_ = std::move(data_pipe_.producer_handle);
154
155 // TODO(ananta)
156 // Move the asynchronous reading and mojo pipe handling code to a helper
157 // class. That would also need a change to BlobURLLoader.
158
159 // Wait for the data pipe to be ready to accept data.
160 writable_handle_watcher_.Watch(
161 response_body_stream_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
162 base::Bind(&AppCacheURLLoaderJob::OnResponseBodyStreamReady,
163 StaticAsWeakPtr(this)));
164
165 if (client_info_)
166 SendResponseInfo();
167
168 ReadMore();
169 } else {
170 // Error case here. We fallback to the network.
171 DeliverNetworkResponse();
172 AppCacheHistograms::CountResponseRetrieval(
173 false, IsResourceTypeFrame(request_.resource_type),
174 manifest_url_.GetOrigin());
175
176 cache_entry_not_found_ = true;
177 }
178 }
179
180 void AppCacheURLLoaderJob::OnReadComplete(int result) {
181 DLOG(WARNING) << "AppCache read completed with result: " << result;
182
183 bool is_main_resource = IsResourceTypeFrame(request_.resource_type);
184
185 if (result == 0) {
186 NotifyCompleted(result);
187 AppCacheHistograms::CountResponseRetrieval(true, is_main_resource,
188 manifest_url_.GetOrigin());
189 return;
190 } else if (result < 0) {
191 // TODO(ananta)
192 // Populate the relevant fields of the ResourceRequestCompletionStatus
193 // structure.
194 NotifyCompleted(result);
195 AppCacheHistograms::CountResponseRetrieval(false, is_main_resource,
196 manifest_url_.GetOrigin());
197 return;
198 }
199
200 uint32_t bytes_written = static_cast<uint32_t>(result);
201 response_body_stream_ = pending_write_->Complete(bytes_written);
202 pending_write_ = nullptr;
203 ReadMore();
204 }
205
206 void AppCacheURLLoaderJob::OnConnectionError() {
207 if (storage_.get())
208 storage_->CancelDelegateCallbacks(this);
209 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
210 }
211
212 void AppCacheURLLoaderJob::SendResponseInfo() {
213 DCHECK(client_info_);
214
215 // If this is null it means the response information was sent to the client.
216 if (!data_pipe_.consumer_handle.is_valid())
217 return;
218
219 const net::HttpResponseInfo* http_info = info_->http_response_info();
220
221 ResourceResponseHead response_head;
222 response_head.headers = http_info->headers;
223
224 // TODO(ananta)
225 // Copy more fields.
226 http_info->headers->GetMimeType(&response_head.mime_type);
227 http_info->headers->GetCharset(&response_head.charset);
228
229 response_head.request_time = http_info->request_time;
230 response_head.response_time = http_info->response_time;
231 response_head.content_length = info_->response_data_size();
232
233 client_info_->OnReceiveResponse(response_head, http_info->ssl_info,
234 mojom::DownloadedTempFilePtr());
235
236 client_info_->OnStartLoadingResponseBody(
237 std::move(data_pipe_.consumer_handle));
238 }
239
240 void AppCacheURLLoaderJob::ReadMore() {
241 DCHECK(!pending_write_.get());
242
243 uint32_t num_bytes;
244 // TODO: we should use the abstractions in MojoAsyncResourceHandler.
245 MojoResult result = NetToMojoPendingBuffer::BeginWrite(
246 &response_body_stream_, &pending_write_, &num_bytes);
247 if (result == MOJO_RESULT_SHOULD_WAIT) {
248 // The pipe is full. We need to wait for it to have more space.
249 writable_handle_watcher_.ArmOrNotify();
250 return;
251 } else if (result != MOJO_RESULT_OK) {
252 // The response body stream is in a bad state. Bail.
253 // TODO(ananta)
254 // Add proper error handling here.
255 NotifyCompleted(net::ERR_FAILED);
256 writable_handle_watcher_.Cancel();
257 response_body_stream_.reset();
258 return;
259 }
260
261 CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes);
262 scoped_refptr<NetToMojoIOBuffer> buffer =
263 new NetToMojoIOBuffer(pending_write_.get());
264
265 reader_->ReadData(
266 buffer.get(), info_->response_data_size(),
267 base::Bind(&AppCacheURLLoaderJob::OnReadComplete, StaticAsWeakPtr(this)));
268 }
269
270 void AppCacheURLLoaderJob::OnResponseBodyStreamReady(MojoResult result) {
271 // TODO(ananta)
272 // Add proper error handling here.
273 if (result != MOJO_RESULT_OK) {
274 DCHECK(false);
275 NotifyCompleted(net::ERR_FAILED);
276 }
277 ReadMore();
278 }
279
280 void AppCacheURLLoaderJob::NotifyCompleted(int error_code) {
281 if (storage_.get())
282 storage_->CancelDelegateCallbacks(this);
283 // TODO(ananta)
284 // Fill other details in the ResourceRequestCompletionStatus structure.
285 ResourceRequestCompletionStatus request_complete_data;
286 request_complete_data.error_code = error_code;
287 client_info_->OnComplete(request_complete_data);
288 }
52 289
53 } // namespace content 290 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/appcache/appcache_url_loader_job.h ('k') | content/browser/appcache/appcache_url_loader_request.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698