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

Side by Side Diff: content/browser/service_worker/service_worker_write_to_cache_job.cc

Issue 1459333002: Revert "Reland: URLRequestJob: change ReadRawData contract" (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/service_worker/service_worker_write_to_cache_job.h" 5 #include "content/browser/service_worker/service_worker_write_to_cache_job.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/strings/stringprintf.h" 9 #include "base/strings/stringprintf.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
12 #include "content/browser/service_worker/service_worker_cache_writer.h" 11 #include "content/browser/service_worker/service_worker_cache_writer.h"
13 #include "content/browser/service_worker/service_worker_context_core.h" 12 #include "content/browser/service_worker/service_worker_context_core.h"
14 #include "content/browser/service_worker/service_worker_disk_cache.h" 13 #include "content/browser/service_worker/service_worker_disk_cache.h"
15 #include "content/browser/service_worker/service_worker_metrics.h" 14 #include "content/browser/service_worker/service_worker_metrics.h"
16 #include "content/common/service_worker/service_worker_types.h" 15 #include "content/common/service_worker/service_worker_types.h"
17 #include "content/common/service_worker/service_worker_utils.h" 16 #include "content/common/service_worker/service_worker_utils.h"
18 #include "net/base/io_buffer.h" 17 #include "net/base/io_buffer.h"
19 #include "net/base/net_errors.h" 18 #include "net/base/net_errors.h"
20 #include "net/http/http_network_session.h" 19 #include "net/http/http_network_session.h"
(...skipping 20 matching lines...) Expand all
41 "The script resource is behind a redirect, which is disallowed."; 40 "The script resource is behind a redirect, which is disallowed.";
42 const char kServiceWorkerAllowed[] = "Service-Worker-Allowed"; 41 const char kServiceWorkerAllowed[] = "Service-Worker-Allowed";
43 42
44 // The net error code used when the job fails the update attempt because the new 43 // The net error code used when the job fails the update attempt because the new
45 // script is byte-by-byte identical to the incumbent script. This error is shown 44 // script is byte-by-byte identical to the incumbent script. This error is shown
46 // in DevTools and in netlog, so we want something obscure enough that it won't 45 // in DevTools and in netlog, so we want something obscure enough that it won't
47 // conflict with a legitimate network error, and not too alarming if seen by 46 // conflict with a legitimate network error, and not too alarming if seen by
48 // developers. 47 // developers.
49 // TODO(falken): Redesign this class so we don't have to fail at the network 48 // TODO(falken): Redesign this class so we don't have to fail at the network
50 // stack layer just to cancel the update. 49 // stack layer just to cancel the update.
51 const net::Error kIdenticalScriptError = net::ERR_FILE_EXISTS; 50 const int kIdenticalScriptError = net::ERR_FILE_EXISTS;
52 51
53 } // namespace 52 } // namespace
54 53
55 ServiceWorkerWriteToCacheJob::ServiceWorkerWriteToCacheJob( 54 ServiceWorkerWriteToCacheJob::ServiceWorkerWriteToCacheJob(
56 net::URLRequest* request, 55 net::URLRequest* request,
57 net::NetworkDelegate* network_delegate, 56 net::NetworkDelegate* network_delegate,
58 ResourceType resource_type, 57 ResourceType resource_type,
59 base::WeakPtr<ServiceWorkerContextCore> context, 58 base::WeakPtr<ServiceWorkerContextCore> context,
60 ServiceWorkerVersion* version, 59 ServiceWorkerVersion* version,
61 int extra_load_flags, 60 int extra_load_flags,
(...skipping 11 matching lines...) Expand all
73 did_notify_finished_(false), 72 did_notify_finished_(false),
74 weak_factory_(this) { 73 weak_factory_(this) {
75 InitNetRequest(extra_load_flags); 74 InitNetRequest(extra_load_flags);
76 } 75 }
77 76
78 ServiceWorkerWriteToCacheJob::~ServiceWorkerWriteToCacheJob() { 77 ServiceWorkerWriteToCacheJob::~ServiceWorkerWriteToCacheJob() {
79 DCHECK_EQ(did_notify_started_, did_notify_finished_); 78 DCHECK_EQ(did_notify_started_, did_notify_finished_);
80 } 79 }
81 80
82 void ServiceWorkerWriteToCacheJob::Start() { 81 void ServiceWorkerWriteToCacheJob::Start() {
83 base::ThreadTaskRunnerHandle::Get()->PostTask(
84 FROM_HERE, base::Bind(&ServiceWorkerWriteToCacheJob::StartAsync,
85 weak_factory_.GetWeakPtr()));
86 }
87
88 void ServiceWorkerWriteToCacheJob::StartAsync() {
89 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", 82 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
90 "ServiceWorkerWriteToCacheJob::ExecutingJob", 83 "ServiceWorkerWriteToCacheJob::ExecutingJob",
91 this, 84 this,
92 "URL", request_->url().spec()); 85 "URL", request_->url().spec());
93 if (!context_) { 86 if (!context_) {
94 // NotifyStartError is not safe to call synchronously in Start().
95 NotifyStartError( 87 NotifyStartError(
96 net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); 88 net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED));
97 return; 89 return;
98 } 90 }
99 91
100 // These uses of Unretained are safe because this object is the sole owner of 92 // These uses of Unretained are safe because this object is the sole owner of
101 // |cache_writer_|, which in turn is the sole user of these callbacks. 93 // |cache_writer_|, which in turn is the sole user of these callbacks.
102 cache_writer_.reset(new ServiceWorkerCacheWriter( 94 cache_writer_.reset(new ServiceWorkerCacheWriter(
103 base::Bind(&ServiceWorkerWriteToCacheJob::CreateCacheResponseReader, 95 base::Bind(&ServiceWorkerWriteToCacheJob::CreateCacheResponseReader,
104 base::Unretained(this)), 96 base::Unretained(this)),
105 base::Bind(&ServiceWorkerWriteToCacheJob::CreateCacheResponseWriter, 97 base::Bind(&ServiceWorkerWriteToCacheJob::CreateCacheResponseWriter,
106 base::Unretained(this)))); 98 base::Unretained(this))));
107 version_->script_cache_map()->NotifyStartedCaching(url_, resource_id_); 99 version_->script_cache_map()->NotifyStartedCaching(url_, resource_id_);
108 did_notify_started_ = true; 100 did_notify_started_ = true;
109 StartNetRequest(); 101 StartNetRequest();
110 } 102 }
111 103
112 void ServiceWorkerWriteToCacheJob::Kill() { 104 void ServiceWorkerWriteToCacheJob::Kill() {
113 if (has_been_killed_) 105 if (has_been_killed_)
114 return; 106 return;
115 weak_factory_.InvalidateWeakPtrs(); 107 weak_factory_.InvalidateWeakPtrs();
116 has_been_killed_ = true; 108 has_been_killed_ = true;
117 net_request_.reset(); 109 net_request_.reset();
118 if (did_notify_started_) { 110 if (did_notify_started_) {
119 net::Error error = NotifyFinishedCaching( 111 NotifyFinishedCaching(net::URLRequestStatus::FromError(net::ERR_ABORTED),
120 net::URLRequestStatus::FromError(net::ERR_ABORTED), kKilledError); 112 kKilledError);
121 DCHECK_EQ(net::ERR_ABORTED, error);
122 } 113 }
123 writer_.reset(); 114 writer_.reset();
124 context_.reset(); 115 context_.reset();
125 net::URLRequestJob::Kill(); 116 net::URLRequestJob::Kill();
126 } 117 }
127 118
128 net::LoadState ServiceWorkerWriteToCacheJob::GetLoadState() const { 119 net::LoadState ServiceWorkerWriteToCacheJob::GetLoadState() const {
129 if (writer_ && writer_->IsWritePending()) 120 if (writer_ && writer_->IsWritePending())
130 return net::LOAD_STATE_WAITING_FOR_APPCACHE; 121 return net::LOAD_STATE_WAITING_FOR_APPCACHE;
131 if (net_request_) 122 if (net_request_)
(...skipping 26 matching lines...) Expand all
158 return http_info()->headers->response_code(); 149 return http_info()->headers->response_code();
159 } 150 }
160 151
161 void ServiceWorkerWriteToCacheJob::SetExtraRequestHeaders( 152 void ServiceWorkerWriteToCacheJob::SetExtraRequestHeaders(
162 const net::HttpRequestHeaders& headers) { 153 const net::HttpRequestHeaders& headers) {
163 std::string value; 154 std::string value;
164 DCHECK(!headers.GetHeader(net::HttpRequestHeaders::kRange, &value)); 155 DCHECK(!headers.GetHeader(net::HttpRequestHeaders::kRange, &value));
165 net_request_->SetExtraRequestHeaders(headers); 156 net_request_->SetExtraRequestHeaders(headers);
166 } 157 }
167 158
168 int ServiceWorkerWriteToCacheJob::ReadRawData(net::IOBuffer* buf, 159 bool ServiceWorkerWriteToCacheJob::ReadRawData(net::IOBuffer* buf,
169 int buf_size) { 160 int buf_size,
170 int bytes_read = 0; 161 int* bytes_read) {
171 net::URLRequestStatus status = ReadNetData(buf, buf_size, &bytes_read); 162 net::URLRequestStatus status = ReadNetData(buf, buf_size, bytes_read);
163 SetStatus(status);
172 if (status.is_io_pending()) 164 if (status.is_io_pending())
173 return net::ERR_IO_PENDING; 165 return false;
174 166
175 if (!status.is_success()) { 167 if (!status.is_success()) {
176 net::Error error = NotifyFinishedCaching(status, kFetchScriptError); 168 NotifyDoneHelper(status, kFetchScriptError);
177 DCHECK_EQ(status.error(), error); 169 return false;
178 return error;
179 } 170 }
180 171
181 return HandleNetData(bytes_read); 172 HandleNetData(*bytes_read);
173 status = GetStatus();
174
175 // Synchronous EOFs that do not replace the incumbent entry are considered
176 // failures. Since normally the URLRequestJob's status would be set by
177 // ReadNetData or HandleNetData, this code has to manually fix up the status
178 // to match the failure this function is about to return.
179 if (status.status() == net::URLRequestStatus::SUCCESS && *bytes_read == 0 &&
180 !cache_writer_->did_replace()) {
181 status = net::URLRequestStatus::FromError(kIdenticalScriptError);
182 }
183
184 if (!status.is_success()) {
185 NotifyDoneHelper(status, "");
186 return false;
187 }
188
189 // Since URLRequestStatus::is_success() means "SUCCESS or IO_PENDING", but the
190 // contract of this function is "return true for synchronous successes only",
191 // it is important to test against SUCCESS explicitly here.
192 return status.status() == net::URLRequestStatus::SUCCESS;
182 } 193 }
183 194
184 const net::HttpResponseInfo* ServiceWorkerWriteToCacheJob::http_info() const { 195 const net::HttpResponseInfo* ServiceWorkerWriteToCacheJob::http_info() const {
185 return http_info_.get(); 196 return http_info_.get();
186 } 197 }
187 198
188 void ServiceWorkerWriteToCacheJob::InitNetRequest( 199 void ServiceWorkerWriteToCacheJob::InitNetRequest(
189 int extra_load_flags) { 200 int extra_load_flags) {
190 DCHECK(request()); 201 DCHECK(request());
191 net_request_ = request()->context()->CreateRequest( 202 net_request_ = request()->context()->CreateRequest(
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 } 237 }
227 238
228 void ServiceWorkerWriteToCacheJob::OnReceivedRedirect( 239 void ServiceWorkerWriteToCacheJob::OnReceivedRedirect(
229 net::URLRequest* request, 240 net::URLRequest* request,
230 const net::RedirectInfo& redirect_info, 241 const net::RedirectInfo& redirect_info,
231 bool* defer_redirect) { 242 bool* defer_redirect) {
232 DCHECK_EQ(net_request_.get(), request); 243 DCHECK_EQ(net_request_.get(), request);
233 TRACE_EVENT0("ServiceWorker", 244 TRACE_EVENT0("ServiceWorker",
234 "ServiceWorkerWriteToCacheJob::OnReceivedRedirect"); 245 "ServiceWorkerWriteToCacheJob::OnReceivedRedirect");
235 // Script resources can't redirect. 246 // Script resources can't redirect.
236 NotifyStartErrorHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, 247 NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
237 net::ERR_UNSAFE_REDIRECT), 248 net::ERR_UNSAFE_REDIRECT),
238 kRedirectError); 249 kRedirectError);
239 } 250 }
240 251
241 void ServiceWorkerWriteToCacheJob::OnAuthRequired( 252 void ServiceWorkerWriteToCacheJob::OnAuthRequired(
242 net::URLRequest* request, 253 net::URLRequest* request,
243 net::AuthChallengeInfo* auth_info) { 254 net::AuthChallengeInfo* auth_info) {
244 DCHECK_EQ(net_request_.get(), request); 255 DCHECK_EQ(net_request_.get(), request);
245 TRACE_EVENT0("ServiceWorker", 256 TRACE_EVENT0("ServiceWorker",
246 "ServiceWorkerWriteToCacheJob::OnAuthRequired"); 257 "ServiceWorkerWriteToCacheJob::OnAuthRequired");
247 // TODO(michaeln): Pass this thru to our jobs client. 258 // TODO(michaeln): Pass this thru to our jobs client.
248 NotifyStartErrorHelper( 259 NotifyDoneHelper(
249 net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED), 260 net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED),
250 kClientAuthenticationError); 261 kClientAuthenticationError);
251 } 262 }
252 263
253 void ServiceWorkerWriteToCacheJob::OnCertificateRequested( 264 void ServiceWorkerWriteToCacheJob::OnCertificateRequested(
254 net::URLRequest* request, 265 net::URLRequest* request,
255 net::SSLCertRequestInfo* cert_request_info) { 266 net::SSLCertRequestInfo* cert_request_info) {
256 DCHECK_EQ(net_request_.get(), request); 267 DCHECK_EQ(net_request_.get(), request);
257 TRACE_EVENT0("ServiceWorker", 268 TRACE_EVENT0("ServiceWorker",
258 "ServiceWorkerWriteToCacheJob::OnCertificateRequested"); 269 "ServiceWorkerWriteToCacheJob::OnCertificateRequested");
259 // TODO(michaeln): Pass this thru to our jobs client. 270 // TODO(michaeln): Pass this thru to our jobs client.
260 // see NotifyCertificateRequested. 271 // see NotifyCertificateRequested.
261 NotifyStartErrorHelper( 272 NotifyDoneHelper(
262 net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED), 273 net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED),
263 kClientAuthenticationError); 274 kClientAuthenticationError);
264 } 275 }
265 276
266 void ServiceWorkerWriteToCacheJob::OnSSLCertificateError( 277 void ServiceWorkerWriteToCacheJob::OnSSLCertificateError(
267 net::URLRequest* request, 278 net::URLRequest* request,
268 const net::SSLInfo& ssl_info, 279 const net::SSLInfo& ssl_info,
269 bool fatal) { 280 bool fatal) {
270 DCHECK_EQ(net_request_.get(), request); 281 DCHECK_EQ(net_request_.get(), request);
271 TRACE_EVENT0("ServiceWorker", 282 TRACE_EVENT0("ServiceWorker",
272 "ServiceWorkerWriteToCacheJob::OnSSLCertificateError"); 283 "ServiceWorkerWriteToCacheJob::OnSSLCertificateError");
273 // TODO(michaeln): Pass this thru to our jobs client, 284 // TODO(michaeln): Pass this thru to our jobs client,
274 // see NotifySSLCertificateError. 285 // see NotifySSLCertificateError.
275 NotifyStartErrorHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, 286 NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
276 net::ERR_INSECURE_RESPONSE), 287 net::ERR_INSECURE_RESPONSE),
277 kSSLError); 288 kSSLError);
278 } 289 }
279 290
280 void ServiceWorkerWriteToCacheJob::OnBeforeNetworkStart( 291 void ServiceWorkerWriteToCacheJob::OnBeforeNetworkStart(
281 net::URLRequest* request, 292 net::URLRequest* request,
282 bool* defer) { 293 bool* defer) {
283 DCHECK_EQ(net_request_.get(), request); 294 DCHECK_EQ(net_request_.get(), request);
284 TRACE_EVENT0("ServiceWorker", 295 TRACE_EVENT0("ServiceWorker",
285 "ServiceWorkerWriteToCacheJob::OnBeforeNetworkStart"); 296 "ServiceWorkerWriteToCacheJob::OnBeforeNetworkStart");
286 NotifyBeforeNetworkStart(defer); 297 NotifyBeforeNetworkStart(defer);
287 } 298 }
288 299
289 void ServiceWorkerWriteToCacheJob::OnResponseStarted( 300 void ServiceWorkerWriteToCacheJob::OnResponseStarted(
290 net::URLRequest* request) { 301 net::URLRequest* request) {
291 DCHECK_EQ(net_request_.get(), request); 302 DCHECK_EQ(net_request_.get(), request);
292 if (!request->status().is_success()) { 303 if (!request->status().is_success()) {
293 NotifyStartErrorHelper(request->status(), kFetchScriptError); 304 NotifyDoneHelper(request->status(), kFetchScriptError);
294 return; 305 return;
295 } 306 }
296 if (request->GetResponseCode() / 100 != 2) { 307 if (request->GetResponseCode() / 100 != 2) {
297 std::string error_message = 308 std::string error_message =
298 base::StringPrintf(kBadHTTPResponseError, request->GetResponseCode()); 309 base::StringPrintf(kBadHTTPResponseError, request->GetResponseCode());
299 NotifyStartErrorHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, 310 NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
300 net::ERR_INVALID_RESPONSE), 311 net::ERR_INVALID_RESPONSE),
301 error_message); 312 error_message);
302 // TODO(michaeln): Instead of error'ing immediately, send the net 313 // TODO(michaeln): Instead of error'ing immediately, send the net
303 // response to our consumer, just don't cache it? 314 // response to our consumer, just don't cache it?
304 return; 315 return;
305 } 316 }
306 // OnSSLCertificateError is not called when the HTTPS connection is reused. 317 // OnSSLCertificateError is not called when the HTTPS connection is reused.
307 // So we check cert_status here. 318 // So we check cert_status here.
308 if (net::IsCertStatusError(request->ssl_info().cert_status)) { 319 if (net::IsCertStatusError(request->ssl_info().cert_status)) {
309 const net::HttpNetworkSession::Params* session_params = 320 const net::HttpNetworkSession::Params* session_params =
310 request->context()->GetNetworkSessionParams(); 321 request->context()->GetNetworkSessionParams();
311 if (!session_params || !session_params->ignore_certificate_errors) { 322 if (!session_params || !session_params->ignore_certificate_errors) {
312 NotifyStartErrorHelper( 323 NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
313 net::URLRequestStatus(net::URLRequestStatus::FAILED, 324 net::ERR_INSECURE_RESPONSE),
314 net::ERR_INSECURE_RESPONSE), 325 kSSLError);
315 kSSLError);
316 return; 326 return;
317 } 327 }
318 } 328 }
319 329
320 if (version_->script_url() == url_) { 330 if (version_->script_url() == url_) {
321 std::string mime_type; 331 std::string mime_type;
322 request->GetMimeType(&mime_type); 332 request->GetMimeType(&mime_type);
323 if (mime_type != "application/x-javascript" && 333 if (mime_type != "application/x-javascript" &&
324 mime_type != "text/javascript" && 334 mime_type != "text/javascript" &&
325 mime_type != "application/javascript") { 335 mime_type != "application/javascript") {
326 std::string error_message = 336 std::string error_message =
327 mime_type.empty() 337 mime_type.empty()
328 ? kNoMIMEError 338 ? kNoMIMEError
329 : base::StringPrintf(kBadMIMEError, mime_type.c_str()); 339 : base::StringPrintf(kBadMIMEError, mime_type.c_str());
330 NotifyStartErrorHelper( 340 NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
331 net::URLRequestStatus(net::URLRequestStatus::FAILED, 341 net::ERR_INSECURE_RESPONSE),
332 net::ERR_INSECURE_RESPONSE), 342 error_message);
333 error_message);
334 return; 343 return;
335 } 344 }
336 345
337 if (!CheckPathRestriction(request)) 346 if (!CheckPathRestriction(request))
338 return; 347 return;
339 348
340 version_->SetMainScriptHttpResponseInfo(net_request_->response_info()); 349 version_->SetMainScriptHttpResponseInfo(net_request_->response_info());
341 } 350 }
342 351
343 if (net_request_->response_info().network_accessed) 352 if (net_request_->response_info().network_accessed)
(...skipping 15 matching lines...) Expand all
359 void ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete(net::Error error) { 368 void ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete(net::Error error) {
360 DCHECK_NE(net::ERR_IO_PENDING, error); 369 DCHECK_NE(net::ERR_IO_PENDING, error);
361 if (error != net::OK) { 370 if (error != net::OK) {
362 NotifyStartError(net::URLRequestStatus::FromError(error)); 371 NotifyStartError(net::URLRequestStatus::FromError(error));
363 return; 372 return;
364 } 373 }
365 SetStatus(net::URLRequestStatus()); 374 SetStatus(net::URLRequestStatus());
366 NotifyHeadersComplete(); 375 NotifyHeadersComplete();
367 } 376 }
368 377
378 void ServiceWorkerWriteToCacheJob::HandleNetData(int bytes_read) {
379 io_buffer_bytes_ = bytes_read;
380 net::Error error = cache_writer_->MaybeWriteData(
381 io_buffer_.get(), bytes_read,
382 base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteDataComplete,
383 weak_factory_.GetWeakPtr()));
384 SetStatus(net::URLRequestStatus::FromError(error));
385
386 // In case of ERR_IO_PENDING, this logic is done in OnWriteDataComplete.
387 if (error != net::ERR_IO_PENDING && bytes_read == 0) {
388 NotifyFinishedCaching(net::URLRequestStatus::FromError(error),
389 std::string());
390 }
391 }
392
369 void ServiceWorkerWriteToCacheJob::OnWriteDataComplete(net::Error error) { 393 void ServiceWorkerWriteToCacheJob::OnWriteDataComplete(net::Error error) {
370 SetStatus(net::URLRequestStatus::FromError(error)); 394 SetStatus(net::URLRequestStatus::FromError(error));
371 DCHECK_NE(net::ERR_IO_PENDING, error); 395 DCHECK_NE(net::ERR_IO_PENDING, error);
372 if (io_buffer_bytes_ == 0) 396 if (io_buffer_bytes_ == 0) {
373 error = NotifyFinishedCaching(net::URLRequestStatus::FromError(error), ""); 397 NotifyDoneHelper(net::URLRequestStatus::FromError(error), std::string());
374 ReadRawDataComplete(error == net::OK ? io_buffer_bytes_ : error); 398 }
399 NotifyReadComplete(error == net::OK ? io_buffer_bytes_ : error);
375 } 400 }
376 401
377 void ServiceWorkerWriteToCacheJob::OnReadCompleted(net::URLRequest* request, 402 void ServiceWorkerWriteToCacheJob::OnReadCompleted(net::URLRequest* request,
378 int bytes_read) { 403 int bytes_read) {
379 DCHECK_EQ(net_request_.get(), request); 404 DCHECK_EQ(net_request_.get(), request);
380
381 int result;
382 if (bytes_read < 0) { 405 if (bytes_read < 0) {
383 DCHECK(!request->status().is_success()); 406 DCHECK(!request->status().is_success());
384 result = NotifyFinishedCaching(request->status(), kFetchScriptError); 407 NotifyDoneHelper(request->status(), kFetchScriptError);
385 } else { 408 return;
386 result = HandleNetData(bytes_read);
387 } 409 }
388 410 HandleNetData(bytes_read);
389 // ReadRawDataComplete will be called in OnWriteDataComplete, so return early. 411 // HandleNetData can cause status of this job to change. If the status changes
390 if (result == net::ERR_IO_PENDING) 412 // to IO_PENDING, that means HandleNetData has pending IO, and
391 return; 413 // NotifyReadComplete will be called later by the appropriate callback.
392 414 if (!GetStatus().is_io_pending()) {
393 ReadRawDataComplete(result); 415 int result = GetStatus().status() == net::URLRequestStatus::SUCCESS
416 ? bytes_read
417 : GetStatus().error();
418 // If bytes_read is 0, HandleNetData synchronously completed and this job is
419 // at EOF.
420 if (bytes_read == 0)
421 NotifyDoneHelper(GetStatus(), std::string());
422 NotifyReadComplete(result);
423 }
394 } 424 }
395 425
396 bool ServiceWorkerWriteToCacheJob::CheckPathRestriction( 426 bool ServiceWorkerWriteToCacheJob::CheckPathRestriction(
397 net::URLRequest* request) { 427 net::URLRequest* request) {
398 std::string service_worker_allowed; 428 std::string service_worker_allowed;
399 const net::HttpResponseHeaders* headers = request->response_headers(); 429 const net::HttpResponseHeaders* headers = request->response_headers();
400 bool has_header = headers->EnumerateHeader(nullptr, kServiceWorkerAllowed, 430 bool has_header = headers->EnumerateHeader(nullptr, kServiceWorkerAllowed,
401 &service_worker_allowed); 431 &service_worker_allowed);
402 432
403 std::string error_message; 433 std::string error_message;
404 if (!ServiceWorkerUtils::IsPathRestrictionSatisfied( 434 if (!ServiceWorkerUtils::IsPathRestrictionSatisfied(
405 version_->scope(), url_, 435 version_->scope(), url_,
406 has_header ? &service_worker_allowed : nullptr, &error_message)) { 436 has_header ? &service_worker_allowed : nullptr, &error_message)) {
407 NotifyStartErrorHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, 437 NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
408 net::ERR_INSECURE_RESPONSE), 438 net::ERR_INSECURE_RESPONSE),
409 error_message); 439 error_message);
410 return false; 440 return false;
411 } 441 }
412 return true; 442 return true;
413 } 443 }
414 444
415 int ServiceWorkerWriteToCacheJob::HandleNetData(int bytes_read) { 445 void ServiceWorkerWriteToCacheJob::NotifyDoneHelper(
416 io_buffer_bytes_ = bytes_read;
417 net::Error error = cache_writer_->MaybeWriteData(
418 io_buffer_.get(), bytes_read,
419 base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteDataComplete,
420 weak_factory_.GetWeakPtr()));
421
422 // In case of ERR_IO_PENDING, this logic is done in OnWriteDataComplete.
423 if (error != net::ERR_IO_PENDING && bytes_read == 0) {
424 error = NotifyFinishedCaching(net::URLRequestStatus::FromError(error),
425 std::string());
426 }
427 return error == net::OK ? bytes_read : error;
428 }
429
430 void ServiceWorkerWriteToCacheJob::NotifyStartErrorHelper(
431 const net::URLRequestStatus& status, 446 const net::URLRequestStatus& status,
432 const std::string& status_message) { 447 const std::string& status_message) {
433 DCHECK(!status.is_io_pending()); 448 DCHECK(!status.is_io_pending());
434 449
435 net::Error error = NotifyFinishedCaching(status, status_message); 450 // Note that NotifyFinishedCaching has logic in it to detect the special case
436 // The special case mentioned in NotifyFinishedCaching about script being 451 // mentioned below as well.
437 // identical does not apply here, since the entire body needs to be read 452 NotifyFinishedCaching(status, status_message);
438 // before this is relevant.
439 DCHECK_EQ(status.error(), error);
440 453
441 net::URLRequestStatus reported_status = status; 454 net::URLRequestStatus reported_status = status;
442 std::string reported_status_message = status_message; 455 std::string reported_status_message = status_message;
443 456
457 // A strange special case: requests that successfully fetch the entire
458 // ServiceWorker and write it back, but which did not replace the incumbent
459 // script because the new script was identical, are considered to have failed.
460 if (status.is_success() && !cache_writer_->did_replace()) {
461 reported_status = net::URLRequestStatus::FromError(kIdenticalScriptError);
462 reported_status_message = "";
463 }
464
444 SetStatus(reported_status); 465 SetStatus(reported_status);
445 NotifyStartError(reported_status); 466 NotifyDone(reported_status);
446 } 467 }
447 468
448 net::Error ServiceWorkerWriteToCacheJob::NotifyFinishedCaching( 469 void ServiceWorkerWriteToCacheJob::NotifyFinishedCaching(
449 net::URLRequestStatus status, 470 net::URLRequestStatus status,
450 const std::string& status_message) { 471 const std::string& status_message) {
451 net::Error result = static_cast<net::Error>(status.error());
452 if (did_notify_finished_) 472 if (did_notify_finished_)
453 return result; 473 return;
454
455 int size = -1;
456 if (status.is_success())
457 size = cache_writer_->bytes_written();
458 474
459 // If all the calls to MaybeWriteHeaders/MaybeWriteData succeeded, but the 475 // If all the calls to MaybeWriteHeaders/MaybeWriteData succeeded, but the
460 // incumbent entry wasn't actually replaced because the new entry was 476 // incumbent entry wasn't actually replaced because the new entry was
461 // equivalent, the new version didn't actually install because it already 477 // equivalent, the new version didn't actually install because it already
462 // exists. 478 // exists.
463 if (status.status() == net::URLRequestStatus::SUCCESS && 479 if (status.status() == net::URLRequestStatus::SUCCESS &&
464 !cache_writer_->did_replace()) { 480 !cache_writer_->did_replace()) {
465 result = kIdenticalScriptError; 481 status = net::URLRequestStatus::FromError(kIdenticalScriptError);
466 status = net::URLRequestStatus::FromError(result);
467 version_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS); 482 version_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS);
468 version_->script_cache_map()->NotifyFinishedCaching(url_, size, status,
469 std::string());
470 } else {
471 version_->script_cache_map()->NotifyFinishedCaching(url_, size, status,
472 status_message);
473 } 483 }
474 484
485 int size = -1;
486 if (status.is_success())
487 size = cache_writer_->bytes_written();
488
489 version_->script_cache_map()->NotifyFinishedCaching(url_, size, status,
490 status_message);
475 did_notify_finished_ = true; 491 did_notify_finished_ = true;
476 return result;
477 } 492 }
478 493
479 scoped_ptr<ServiceWorkerResponseReader> 494 scoped_ptr<ServiceWorkerResponseReader>
480 ServiceWorkerWriteToCacheJob::CreateCacheResponseReader() { 495 ServiceWorkerWriteToCacheJob::CreateCacheResponseReader() {
481 if (incumbent_resource_id_ == kInvalidServiceWorkerResourceId || 496 if (incumbent_resource_id_ == kInvalidServiceWorkerResourceId ||
482 version_->skip_script_comparison()) { 497 version_->skip_script_comparison()) {
483 return nullptr; 498 return nullptr;
484 } 499 }
485 return context_->storage()->CreateResponseReader(incumbent_resource_id_); 500 return context_->storage()->CreateResponseReader(incumbent_resource_id_);
486 } 501 }
487 502
488 scoped_ptr<ServiceWorkerResponseWriter> 503 scoped_ptr<ServiceWorkerResponseWriter>
489 ServiceWorkerWriteToCacheJob::CreateCacheResponseWriter() { 504 ServiceWorkerWriteToCacheJob::CreateCacheResponseWriter() {
490 return context_->storage()->CreateResponseWriter(resource_id_); 505 return context_->storage()->CreateResponseWriter(resource_id_);
491 } 506 }
492 507
493 } // namespace content 508 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/service_worker/service_worker_write_to_cache_job.h ('k') | content/browser/streams/stream_url_request_job.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698