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

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: Address next round of review comments 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 #include "content/browser/appcache/appcache_histograms.h"
7 #include "content/common/net_adapters.h"
8 #include "content/public/common/resource_type.h"
7 9
8 namespace content { 10 namespace content {
9 11
10 AppCacheURLLoaderJob::~AppCacheURLLoaderJob() {} 12 AppCacheURLLoaderJob::~AppCacheURLLoaderJob() {
13 if (storage_)
michaeln 2017/06/09 19:59:53 this is where we're likely to crash in some cases,
ananta 2017/06/09 20:39:33 Added weakptr support to AppCacheStorage.
14 storage_->CancelDelegateCallbacks(this);
15 }
11 16
12 void AppCacheURLLoaderJob::Kill() {} 17 void AppCacheURLLoaderJob::Kill() {}
13 18
14 bool AppCacheURLLoaderJob::IsStarted() const { 19 bool AppCacheURLLoaderJob::IsStarted() const {
15 return false; 20 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 } 21 }
37 22
38 void AppCacheURLLoaderJob::DeliverAppCachedResponse(const GURL& manifest_url, 23 void AppCacheURLLoaderJob::DeliverAppCachedResponse(const GURL& manifest_url,
39 int64_t cache_id, 24 int64_t cache_id,
40 const AppCacheEntry& entry, 25 const AppCacheEntry& entry,
41 bool is_fallback) {} 26 bool is_fallback) {
42 27 delivery_type_ = APPCACHED_DELIVERY;
43 void AppCacheURLLoaderJob::DeliverNetworkResponse() {} 28
44 29 AppCacheHistograms::AddAppCacheJobStartDelaySample(base::TimeTicks::Now() -
45 void AppCacheURLLoaderJob::DeliverErrorResponse() {} 30 start_time_tick_);
31
32 manifest_url_ = manifest_url;
33 cache_id_ = cache_id;
34 entry_ = entry;
35 is_fallback_ = is_fallback;
36
37 // TODO(ananta)
38 // Implement the AppCacheServiceImpl::Observer interface or add weak pointer
39 // support to it.
40 storage_->LoadResponseInfo(manifest_url_, entry_.response_id(), this);
41 }
42
43 void AppCacheURLLoaderJob::DeliverNetworkResponse() {
44 delivery_type_ = NETWORK_DELIVERY;
45
46 AppCacheHistograms::AddNetworkJobStartDelaySample(base::TimeTicks::Now() -
47 start_time_tick_);
48
49 DCHECK(!loader_callback_.is_null());
50 // In network service land, if we are processing a navigation request, we
51 // need to inform the loader callback that we are not going to handle this
52 // request. The loader callback is valid only for navigation requests.
53 std::move(loader_callback_).Run(StartLoaderCallback());
54 }
55
56 void AppCacheURLLoaderJob::DeliverErrorResponse() {
57 delivery_type_ = ERROR_DELIVERY;
58 storage_ = nullptr;
michaeln 2017/06/09 19:59:54 i'd suggest moving this into the NotifyCompleted h
ananta 2017/06/09 20:39:32 Done. We don't need to set it to null anymore as w
59 // TODO(ananta)
60 // Fill up the correct error code here and add support in NotifyError() to
61 // generate a proper error response.
62 // We may need to call OnReceiveResponse on the client. That requires HTTP
63 // header generation etc.
64 NotifyCompleted(net::ERR_UNEXPECTED);
65 AppCacheHistograms::AddErrorJobStartDelaySample(base::TimeTicks::Now() -
66 start_time_tick_);
67 }
46 68
47 const GURL& AppCacheURLLoaderJob::GetURL() const { 69 const GURL& AppCacheURLLoaderJob::GetURL() const {
48 return url_; 70 return request_.url;
49 } 71 }
50 72
51 AppCacheURLLoaderJob::AppCacheURLLoaderJob() {} 73 AppCacheURLLoaderJob* AppCacheURLLoaderJob::AsURLLoaderJob() {
74 return this;
75 }
76
77 void AppCacheURLLoaderJob::FollowRedirect() {
78 DCHECK(false);
79 }
80
81 void AppCacheURLLoaderJob::SetPriority(net::RequestPriority priority,
82 int32_t intra_priority_value) {
83 NOTREACHED() << "We don't support SetPriority()";
84 }
85
86 void AppCacheURLLoaderJob::Start(mojom::URLLoaderRequest request,
87 mojom::URLLoaderClientPtr client) {
88 DCHECK(!binding_.is_bound());
89 binding_.Bind(std::move(request));
90
91 binding_.set_connection_error_handler(base::Bind(
92 &AppCacheURLLoaderJob::OnConnectionError, StaticAsWeakPtr(this)));
93
94 client_info_ = std::move(client);
95
96 // Send the cached AppCacheResponse if any.
97 if (info_.get())
98 SendResponseInfo();
99 }
100
101 AppCacheURLLoaderJob::AppCacheURLLoaderJob(const ResourceRequest& request,
102 AppCacheStorage* storage)
103 : request_(request),
104 storage_(storage),
105 start_time_tick_(base::TimeTicks::Now()),
106 cache_id_(kAppCacheNoCacheId),
107 is_fallback_(false),
108 binding_(this),
109 writable_handle_watcher_(FROM_HERE,
110 mojo::SimpleWatcher::ArmingPolicy::MANUAL) {}
111
112 void AppCacheURLLoaderJob::OnResponseInfoLoaded(
113 AppCacheResponseInfo* response_info,
114 int64_t response_id) {
115 DCHECK(IsDeliveringAppCacheResponse());
116
michaeln 2017/06/09 19:59:54 As coded, i'm the raw storage_ptr_ is real likely
ananta 2017/06/09 20:39:32 We have a weakptr now. Checked it for null at the
117 if (response_info) {
118 info_ = response_info;
119 reader_.reset(
120 storage_->CreateResponseReader(manifest_url_, entry_.response_id()));
121
122 DCHECK(!loader_callback_.is_null());
123 std::move(loader_callback_)
124 .Run(base::Bind(&AppCacheURLLoaderJob::Start, StaticAsWeakPtr(this)));
125
126 // TODO(ananta)
127 // Handle range requests.
128
129 response_body_stream_ = std::move(data_pipe_.producer_handle);
130
131 // TODO(ananta)
132 // Move the asynchronous reading and mojo pipe handling code to a helper
133 // class. That would also need a change to BlobURLLoader.
134
135 // Wait for the data pipe to be ready to accept data.
136 writable_handle_watcher_.Watch(
137 response_body_stream_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
138 base::Bind(&AppCacheURLLoaderJob::OnResponseBodyStreamReady,
139 StaticAsWeakPtr(this)));
140
141 if (client_info_)
142 SendResponseInfo();
143
144 ReadMore();
145 } else {
146 // Error case here. We fallback to the network.
147 DeliverNetworkResponse();
148 AppCacheHistograms::CountResponseRetrieval(
149 false, IsResourceTypeFrame(request_.resource_type),
150 manifest_url_.GetOrigin());
151
152 cache_entry_not_found_ = true;
153 }
154 }
155
156 void AppCacheURLLoaderJob::OnCacheLoaded(AppCache* cache, int64_t cache_id) {
157 NOTREACHED() << "Unhandled at the moment.";
158 }
159
160 void AppCacheURLLoaderJob::OnReadComplete(int result) {
161 DLOG(WARNING) << "AppCache read completed with result: " << result;
162
163 bool is_main_resource = IsResourceTypeFrame(request_.resource_type);
164
165 if (result == 0) {
166 NotifyCompleted(result);
167 AppCacheHistograms::CountResponseRetrieval(true, is_main_resource,
168 manifest_url_.GetOrigin());
169 return;
170 } else if (result < 0) {
171 // TODO(ananta)
172 // Populate the relevant fields of the ResourceRequestCompletionStatus
173 // structure.
174 NotifyCompleted(result);
175 AppCacheHistograms::CountResponseRetrieval(false, is_main_resource,
176 manifest_url_.GetOrigin());
177 return;
178 }
179
180 uint32_t bytes_written = static_cast<uint32_t>(result);
181 response_body_stream_ = pending_write_->Complete(bytes_written);
182 pending_write_ = nullptr;
183 ReadMore();
184 }
185
186 void AppCacheURLLoaderJob::OnConnectionError() {
michaeln 2017/06/09 19:59:53 we definitely want to nullout the storage_ ptr and
ananta 2017/06/09 20:39:32 Done.We don't need to set it to null anymore as we
187 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
188 }
189
190 void AppCacheURLLoaderJob::SendResponseInfo() {
191 DCHECK(client_info_);
192
193 // If this is null it means the response information was sent to the client.
194 if (!data_pipe_.consumer_handle.is_valid())
195 return;
196
197 const net::HttpResponseInfo* http_info = info_->http_response_info();
198
199 ResourceResponseHead response_head;
200 response_head.headers = http_info->headers;
201
202 // TODO(ananta)
203 // Copy more fields.
204 http_info->headers->GetMimeType(&response_head.mime_type);
205 http_info->headers->GetCharset(&response_head.charset);
206
207 response_head.request_time = http_info->request_time;
208 response_head.response_time = http_info->response_time;
209 response_head.content_length = info_->response_data_size();
210
211 client_info_->OnReceiveResponse(response_head, http_info->ssl_info,
212 mojom::DownloadedTempFilePtr());
213
214 client_info_->OnStartLoadingResponseBody(
215 std::move(data_pipe_.consumer_handle));
216 }
217
218 void AppCacheURLLoaderJob::ReadMore() {
219 DCHECK(!pending_write_.get());
220
221 uint32_t num_bytes;
222 // TODO: we should use the abstractions in MojoAsyncResourceHandler.
223 MojoResult result = NetToMojoPendingBuffer::BeginWrite(
224 &response_body_stream_, &pending_write_, &num_bytes);
225 if (result == MOJO_RESULT_SHOULD_WAIT) {
226 // The pipe is full. We need to wait for it to have more space.
227 writable_handle_watcher_.ArmOrNotify();
228 return;
229 } else if (result != MOJO_RESULT_OK) {
230 // The response body stream is in a bad state. Bail.
231 // TODO(ananta)
232 // Add proper error handling here.
233 NotifyCompleted(net::ERR_UNEXPECTED);
234 writable_handle_watcher_.Cancel();
235 response_body_stream_.reset();
236 return;
237 }
238
239 CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes);
240 scoped_refptr<NetToMojoIOBuffer> buffer = new NetToMojoIOBuffer(
241 pending_write_.get());
242
243 reader_->ReadData(
244 buffer.get(), info_->response_data_size(),
245 base::Bind(&AppCacheURLLoaderJob::OnReadComplete, StaticAsWeakPtr(this)));
246 }
247
248 void AppCacheURLLoaderJob::OnResponseBodyStreamReady(MojoResult result) {
249 // TODO(ananta)
250 // Add proper error handling here.
251 if (result != MOJO_RESULT_OK) {
252 DCHECK(false);
253 NotifyCompleted(net::ERR_UNEXPECTED);
254 }
255 ReadMore();
256 }
257
258 void AppCacheURLLoaderJob::NotifyCompleted(int error_code) {
259 // TODO(ananta)
260 // Fill other details in the ResourceRequestCompletionStatus structure.
michaeln 2017/06/09 19:59:53 this method might be a good bottle neck to conditi
ananta 2017/06/09 20:39:32 Done. We don't need to set it to null anymore as w
261 ResourceRequestCompletionStatus request_complete_data;
262 request_complete_data.error_code = error_code;
263 client_info_->OnComplete(request_complete_data);
264 }
52 265
53 } // namespace content 266 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698