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

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

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