[ServiceWorker] Fills SSLInfo of the response from a SW with the SSLInfo of the SW...
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_url_request_job.cc
blob4c6c59dd632cb1f04a08d18752eeb635c2beb5fd
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
3 // found in the LICENSE file.
5 #include "content/browser/service_worker/service_worker_url_request_job.h"
7 #include <map>
8 #include <string>
9 #include <vector>
11 #include "base/bind.h"
12 #include "base/guid.h"
13 #include "base/memory/scoped_vector.h"
14 #include "base/profiler/scoped_tracker.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/time/time.h"
17 #include "content/browser/resource_context_impl.h"
18 #include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
19 #include "content/browser/service_worker/service_worker_provider_host.h"
20 #include "content/browser/streams/stream.h"
21 #include "content/browser/streams/stream_context.h"
22 #include "content/browser/streams/stream_registry.h"
23 #include "content/common/resource_request_body.h"
24 #include "content/common/service_worker/service_worker_types.h"
25 #include "content/public/browser/blob_handle.h"
26 #include "content/public/browser/resource_request_info.h"
27 #include "content/public/browser/service_worker_context.h"
28 #include "content/public/common/referrer.h"
29 #include "net/base/net_errors.h"
30 #include "net/http/http_request_headers.h"
31 #include "net/http/http_response_headers.h"
32 #include "net/http/http_response_info.h"
33 #include "net/http/http_util.h"
34 #include "storage/browser/blob/blob_data_builder.h"
35 #include "storage/browser/blob/blob_data_handle.h"
36 #include "storage/browser/blob/blob_storage_context.h"
37 #include "storage/browser/blob/blob_url_request_job_factory.h"
38 #include "ui/base/page_transition_types.h"
40 namespace content {
42 ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob(
43 net::URLRequest* request,
44 net::NetworkDelegate* network_delegate,
45 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
46 base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
47 const ResourceContext* resource_context,
48 FetchRequestMode request_mode,
49 FetchCredentialsMode credentials_mode,
50 RequestContextType request_context_type,
51 RequestContextFrameType frame_type,
52 scoped_refptr<ResourceRequestBody> body)
53 : net::URLRequestJob(request, network_delegate),
54 provider_host_(provider_host),
55 response_type_(NOT_DETERMINED),
56 is_started_(false),
57 service_worker_response_type_(blink::WebServiceWorkerResponseTypeDefault),
58 blob_storage_context_(blob_storage_context),
59 resource_context_(resource_context),
60 stream_pending_buffer_size_(0),
61 request_mode_(request_mode),
62 credentials_mode_(credentials_mode),
63 request_context_type_(request_context_type),
64 frame_type_(frame_type),
65 fall_back_required_(false),
66 body_(body),
67 weak_factory_(this) {
70 void ServiceWorkerURLRequestJob::FallbackToNetwork() {
71 DCHECK_EQ(NOT_DETERMINED, response_type_);
72 response_type_ = FALLBACK_TO_NETWORK;
73 MaybeStartRequest();
76 void ServiceWorkerURLRequestJob::ForwardToServiceWorker() {
77 DCHECK_EQ(NOT_DETERMINED, response_type_);
78 response_type_ = FORWARD_TO_SERVICE_WORKER;
79 MaybeStartRequest();
82 void ServiceWorkerURLRequestJob::Start() {
83 is_started_ = true;
84 MaybeStartRequest();
87 void ServiceWorkerURLRequestJob::Kill() {
88 net::URLRequestJob::Kill();
89 ClearStream();
90 fetch_dispatcher_.reset();
91 blob_request_.reset();
92 weak_factory_.InvalidateWeakPtrs();
95 net::LoadState ServiceWorkerURLRequestJob::GetLoadState() const {
96 // TODO(kinuko): refine this for better debug.
97 return net::URLRequestJob::GetLoadState();
100 bool ServiceWorkerURLRequestJob::GetCharset(std::string* charset) {
101 if (!http_info())
102 return false;
103 return http_info()->headers->GetCharset(charset);
106 bool ServiceWorkerURLRequestJob::GetMimeType(std::string* mime_type) const {
107 if (!http_info())
108 return false;
109 return http_info()->headers->GetMimeType(mime_type);
112 void ServiceWorkerURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
113 if (!http_info())
114 return;
115 const base::Time request_time = info->request_time;
116 *info = *http_info();
117 info->request_time = request_time;
118 info->response_time = response_time_;
121 void ServiceWorkerURLRequestJob::GetLoadTimingInfo(
122 net::LoadTimingInfo* load_timing_info) const {
123 *load_timing_info = load_timing_info_;
126 int ServiceWorkerURLRequestJob::GetResponseCode() const {
127 if (!http_info())
128 return -1;
129 return http_info()->headers->response_code();
132 void ServiceWorkerURLRequestJob::SetExtraRequestHeaders(
133 const net::HttpRequestHeaders& headers) {
134 std::string range_header;
135 std::vector<net::HttpByteRange> ranges;
136 if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header) ||
137 !net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
138 return;
141 // We don't support multiple range requests in one single URL request.
142 if (ranges.size() == 1U)
143 byte_range_ = ranges[0];
146 bool ServiceWorkerURLRequestJob::ReadRawData(
147 net::IOBuffer* buf, int buf_size, int *bytes_read) {
148 // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
149 tracked_objects::ScopedTracker tracking_profile(
150 FROM_HERE_WITH_EXPLICIT_FUNCTION(
151 "423948 ServiceWorkerURLRequestJob::ReadRawData"));
153 DCHECK(buf);
154 DCHECK_GE(buf_size, 0);
155 DCHECK(bytes_read);
156 DCHECK(waiting_stream_url_.is_empty());
157 if (stream_.get()) {
158 switch (stream_->ReadRawData(buf, buf_size, bytes_read)) {
159 case Stream::STREAM_HAS_DATA:
160 DCHECK_GT(*bytes_read, 0);
161 return true;
162 case Stream::STREAM_COMPLETE:
163 DCHECK(!*bytes_read);
164 return true;
165 case Stream::STREAM_EMPTY:
166 stream_pending_buffer_ = buf;
167 stream_pending_buffer_size_ = buf_size;
168 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
169 return false;
170 case Stream::STREAM_ABORTED:
171 // Handle this as connection reset.
172 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
173 net::ERR_CONNECTION_RESET));
174 return false;
176 NOTREACHED();
177 return false;
180 if (!blob_request_) {
181 *bytes_read = 0;
182 return true;
184 blob_request_->Read(buf, buf_size, bytes_read);
185 net::URLRequestStatus status = blob_request_->status();
186 SetStatus(status);
187 if (status.is_io_pending())
188 return false;
189 return status.is_success();
192 void ServiceWorkerURLRequestJob::OnReceivedRedirect(
193 net::URLRequest* request,
194 const net::RedirectInfo& redirect_info,
195 bool* defer_redirect) {
196 NOTREACHED();
199 void ServiceWorkerURLRequestJob::OnAuthRequired(
200 net::URLRequest* request,
201 net::AuthChallengeInfo* auth_info) {
202 NOTREACHED();
205 void ServiceWorkerURLRequestJob::OnCertificateRequested(
206 net::URLRequest* request,
207 net::SSLCertRequestInfo* cert_request_info) {
208 NOTREACHED();
211 void ServiceWorkerURLRequestJob::OnSSLCertificateError(
212 net::URLRequest* request,
213 const net::SSLInfo& ssl_info,
214 bool fatal) {
215 NOTREACHED();
218 void ServiceWorkerURLRequestJob::OnBeforeNetworkStart(net::URLRequest* request,
219 bool* defer) {
220 NOTREACHED();
223 void ServiceWorkerURLRequestJob::OnResponseStarted(net::URLRequest* request) {
224 // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
225 tracked_objects::ScopedTracker tracking_profile(
226 FROM_HERE_WITH_EXPLICIT_FUNCTION(
227 "423948 ServiceWorkerURLRequestJob::OnResponseStarted"));
229 // TODO(falken): Add Content-Length, Content-Type if they were not provided in
230 // the ServiceWorkerResponse.
231 response_time_ = base::Time::Now();
232 CommitResponseHeader();
235 void ServiceWorkerURLRequestJob::OnReadCompleted(net::URLRequest* request,
236 int bytes_read) {
237 // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
238 tracked_objects::ScopedTracker tracking_profile(
239 FROM_HERE_WITH_EXPLICIT_FUNCTION(
240 "423948 ServiceWorkerURLRequestJob::OnReadCompleted"));
242 SetStatus(request->status());
243 if (!request->status().is_success()) {
244 NotifyDone(request->status());
245 return;
247 NotifyReadComplete(bytes_read);
248 if (bytes_read == 0)
249 NotifyDone(request->status());
252 void ServiceWorkerURLRequestJob::OnDataAvailable(Stream* stream) {
253 // Clear the IO_PENDING status.
254 SetStatus(net::URLRequestStatus());
255 // Do nothing if stream_pending_buffer_ is empty, i.e. there's no ReadRawData
256 // operation waiting for IO completion.
257 if (!stream_pending_buffer_.get())
258 return;
260 // stream_pending_buffer_ is set to the IOBuffer instance provided to
261 // ReadRawData() by URLRequestJob.
263 int bytes_read = 0;
264 switch (stream_->ReadRawData(
265 stream_pending_buffer_.get(), stream_pending_buffer_size_, &bytes_read)) {
266 case Stream::STREAM_HAS_DATA:
267 DCHECK_GT(bytes_read, 0);
268 break;
269 case Stream::STREAM_COMPLETE:
270 // Calling NotifyReadComplete with 0 signals completion.
271 DCHECK(!bytes_read);
272 break;
273 case Stream::STREAM_EMPTY:
274 NOTREACHED();
275 break;
276 case Stream::STREAM_ABORTED:
277 // Handle this as connection reset.
278 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
279 net::ERR_CONNECTION_RESET));
280 break;
283 // Clear the buffers before notifying the read is complete, so that it is
284 // safe for the observer to read.
285 stream_pending_buffer_ = nullptr;
286 stream_pending_buffer_size_ = 0;
287 NotifyReadComplete(bytes_read);
290 void ServiceWorkerURLRequestJob::OnStreamRegistered(Stream* stream) {
291 StreamContext* stream_context =
292 GetStreamContextForResourceContext(resource_context_);
293 stream_context->registry()->RemoveRegisterObserver(waiting_stream_url_);
294 waiting_stream_url_ = GURL();
295 stream_ = stream;
296 stream_->SetReadObserver(this);
297 CommitResponseHeader();
300 const net::HttpResponseInfo* ServiceWorkerURLRequestJob::http_info() const {
301 if (!http_response_info_)
302 return nullptr;
303 if (range_response_info_)
304 return range_response_info_.get();
305 return http_response_info_.get();
308 void ServiceWorkerURLRequestJob::GetExtraResponseInfo(
309 bool* was_fetched_via_service_worker,
310 bool* was_fallback_required_by_service_worker,
311 GURL* original_url_via_service_worker,
312 blink::WebServiceWorkerResponseType* response_type_via_service_worker,
313 base::TimeTicks* fetch_start_time,
314 base::TimeTicks* fetch_ready_time,
315 base::TimeTicks* fetch_end_time) const {
316 if (response_type_ != FORWARD_TO_SERVICE_WORKER) {
317 *was_fetched_via_service_worker = false;
318 *was_fallback_required_by_service_worker = false;
319 *original_url_via_service_worker = GURL();
320 *response_type_via_service_worker =
321 blink::WebServiceWorkerResponseTypeDefault;
322 return;
324 *was_fetched_via_service_worker = true;
325 *was_fallback_required_by_service_worker = fall_back_required_;
326 *original_url_via_service_worker = response_url_;
327 *response_type_via_service_worker = service_worker_response_type_;
328 *fetch_start_time = fetch_start_time_;
329 *fetch_ready_time = fetch_ready_time_;
330 *fetch_end_time = fetch_end_time_;
334 ServiceWorkerURLRequestJob::~ServiceWorkerURLRequestJob() {
335 ClearStream();
338 void ServiceWorkerURLRequestJob::MaybeStartRequest() {
339 if (is_started_ && response_type_ != NOT_DETERMINED) {
340 // Start asynchronously.
341 base::MessageLoop::current()->PostTask(
342 FROM_HERE,
343 base::Bind(&ServiceWorkerURLRequestJob::StartRequest,
344 weak_factory_.GetWeakPtr()));
348 void ServiceWorkerURLRequestJob::StartRequest() {
349 switch (response_type_) {
350 case NOT_DETERMINED:
351 NOTREACHED();
352 return;
354 case FALLBACK_TO_NETWORK:
355 // Restart the request to create a new job. Our request handler will
356 // return nullptr, and the default job (which will hit network) should be
357 // created.
358 NotifyRestartRequired();
359 return;
361 case FORWARD_TO_SERVICE_WORKER:
362 DCHECK(provider_host_ && provider_host_->active_version());
363 DCHECK(!fetch_dispatcher_);
364 // Send a fetch event to the ServiceWorker associated to the
365 // provider_host.
366 fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher(
367 CreateFetchRequest(),
368 provider_host_->active_version(),
369 base::Bind(&ServiceWorkerURLRequestJob::DidPrepareFetchEvent,
370 weak_factory_.GetWeakPtr()),
371 base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent,
372 weak_factory_.GetWeakPtr())));
373 fetch_start_time_ = base::TimeTicks::Now();
374 load_timing_info_.send_start = fetch_start_time_;
375 fetch_dispatcher_->Run();
376 return;
379 NOTREACHED();
382 scoped_ptr<ServiceWorkerFetchRequest>
383 ServiceWorkerURLRequestJob::CreateFetchRequest() {
384 std::string blob_uuid;
385 uint64 blob_size = 0;
386 CreateRequestBodyBlob(&blob_uuid, &blob_size);
387 scoped_ptr<ServiceWorkerFetchRequest> request(
388 new ServiceWorkerFetchRequest());
389 request->mode = request_mode_;
390 request->request_context_type = request_context_type_;
391 request->frame_type = frame_type_;
392 request->url = request_->url();
393 request->method = request_->method();
394 const net::HttpRequestHeaders& headers = request_->extra_request_headers();
395 for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();) {
396 if (ServiceWorkerContext::IsExcludedHeaderNameForFetchEvent(it.name()))
397 continue;
398 request->headers[it.name()] = it.value();
400 request->blob_uuid = blob_uuid;
401 request->blob_size = blob_size;
402 request->credentials_mode = credentials_mode_;
403 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
404 if (info) {
405 request->is_reload = ui::PageTransitionCoreTypeIs(
406 info->GetPageTransition(), ui::PAGE_TRANSITION_RELOAD);
407 request->referrer =
408 Referrer(GURL(request_->referrer()), info->GetReferrerPolicy());
409 } else {
410 CHECK(
411 request_->referrer_policy() ==
412 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE);
413 request->referrer =
414 Referrer(GURL(request_->referrer()), blink::WebReferrerPolicyDefault);
416 return request.Pass();
419 bool ServiceWorkerURLRequestJob::CreateRequestBodyBlob(std::string* blob_uuid,
420 uint64* blob_size) {
421 if (!body_.get() || !blob_storage_context_)
422 return false;
424 // To ensure the blobs stick around until the end of the reading.
425 ScopedVector<storage::BlobDataHandle> handles;
426 ScopedVector<storage::BlobDataSnapshot> snapshots;
427 // TODO(dmurph): Allow blobs to be added below, so that the context can
428 // efficiently re-use blob items for the new blob.
429 std::vector<const ResourceRequestBody::Element*> resolved_elements;
430 for (const ResourceRequestBody::Element& element : (*body_->elements())) {
431 if (element.type() != ResourceRequestBody::Element::TYPE_BLOB) {
432 resolved_elements.push_back(&element);
433 continue;
435 scoped_ptr<storage::BlobDataHandle> handle =
436 blob_storage_context_->GetBlobDataFromUUID(element.blob_uuid());
437 scoped_ptr<storage::BlobDataSnapshot> snapshot = handle->CreateSnapshot();
438 if (snapshot->items().empty())
439 continue;
440 const auto& items = snapshot->items();
441 for (const auto& item : items) {
442 DCHECK_NE(storage::DataElement::TYPE_BLOB, item->type());
443 resolved_elements.push_back(item->data_element_ptr());
445 handles.push_back(handle.release());
446 snapshots.push_back(snapshot.release());
449 const std::string uuid(base::GenerateGUID());
450 uint64 total_size = 0;
452 storage::BlobDataBuilder blob_builder(uuid);
453 for (size_t i = 0; i < resolved_elements.size(); ++i) {
454 const ResourceRequestBody::Element& element = *resolved_elements[i];
455 if (total_size != kuint64max && element.length() != kuint64max)
456 total_size += element.length();
457 else
458 total_size = kuint64max;
459 switch (element.type()) {
460 case ResourceRequestBody::Element::TYPE_BYTES:
461 blob_builder.AppendData(element.bytes(), element.length());
462 break;
463 case ResourceRequestBody::Element::TYPE_FILE:
464 blob_builder.AppendFile(element.path(), element.offset(),
465 element.length(),
466 element.expected_modification_time());
467 break;
468 case ResourceRequestBody::Element::TYPE_BLOB:
469 // Blob elements should be resolved beforehand.
470 NOTREACHED();
471 break;
472 case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM:
473 blob_builder.AppendFileSystemFile(element.filesystem_url(),
474 element.offset(), element.length(),
475 element.expected_modification_time());
476 break;
477 default:
478 NOTIMPLEMENTED();
482 request_body_blob_data_handle_ =
483 blob_storage_context_->AddFinishedBlob(blob_builder);
484 *blob_uuid = uuid;
485 *blob_size = total_size;
486 return true;
489 void ServiceWorkerURLRequestJob::DidPrepareFetchEvent() {
490 fetch_ready_time_ = base::TimeTicks::Now();
493 void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
494 ServiceWorkerStatusCode status,
495 ServiceWorkerFetchEventResult fetch_result,
496 const ServiceWorkerResponse& response) {
497 fetch_dispatcher_.reset();
499 // Check if we're not orphaned.
500 if (!request())
501 return;
503 if (status != SERVICE_WORKER_OK) {
504 // Dispatching event has been failed, returns an error response.
505 // TODO(kinuko): Would be nice to log the error case.
506 DeliverErrorResponse();
507 return;
510 if (fetch_result == SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK) {
511 // When the request_mode is |CORS| or |CORS-with-forced-preflight| we can't
512 // simply fallback to the network in the browser process. It is because the
513 // CORS preflight logic is implemented in the renderer. So we returns a
514 // fall_back_required response to the renderer.
515 if (request_mode_ == FETCH_REQUEST_MODE_CORS ||
516 request_mode_ == FETCH_REQUEST_MODE_CORS_WITH_FORCED_PREFLIGHT) {
517 fall_back_required_ = true;
518 CreateResponseHeader(
519 400, "Service Worker Fallback Required", ServiceWorkerHeaderMap());
520 CommitResponseHeader();
521 return;
523 // Change the response type and restart the request to fallback to
524 // the network.
525 response_type_ = FALLBACK_TO_NETWORK;
526 NotifyRestartRequired();
527 return;
530 // We should have a response now.
531 DCHECK_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, fetch_result);
533 // Treat a response whose status is 0 as a Network Error.
534 if (response.status_code == 0) {
535 NotifyDone(
536 net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED));
537 return;
540 fetch_end_time_ = base::TimeTicks::Now();
541 load_timing_info_.send_end = fetch_end_time_;
543 // Creates a new HttpResponseInfo using the the ServiceWorker script's
544 // HttpResponseInfo to show HTTPS padlock.
545 // TODO(horo): When we support mixed-content (HTTP) no-cors requests from a
546 // ServiceWorker, we have to check the security level of the responses.
547 DCHECK(!http_response_info_);
548 const net::HttpResponseInfo* main_script_http_info =
549 provider_host_->active_version()->GetMainScriptHttpResponseInfo();
550 DCHECK(main_script_http_info);
551 http_response_info_.reset(new net::HttpResponseInfo(*main_script_http_info));
553 // Set up a request for reading the stream.
554 if (response.stream_url.is_valid()) {
555 DCHECK(response.blob_uuid.empty());
556 DCHECK(provider_host_->active_version());
557 streaming_version_ = provider_host_->active_version();
558 streaming_version_->AddStreamingURLRequestJob(this);
559 response_url_ = response.url;
560 service_worker_response_type_ = response.response_type;
561 CreateResponseHeader(
562 response.status_code, response.status_text, response.headers);
563 load_timing_info_.receive_headers_end = base::TimeTicks::Now();
564 StreamContext* stream_context =
565 GetStreamContextForResourceContext(resource_context_);
566 stream_ =
567 stream_context->registry()->GetStream(response.stream_url);
568 if (!stream_.get()) {
569 waiting_stream_url_ = response.stream_url;
570 // Wait for StreamHostMsg_StartBuilding message from the ServiceWorker.
571 stream_context->registry()->SetRegisterObserver(waiting_stream_url_,
572 this);
573 return;
575 stream_->SetReadObserver(this);
576 CommitResponseHeader();
577 return;
579 // Set up a request for reading the blob.
580 if (!response.blob_uuid.empty() && blob_storage_context_) {
581 scoped_ptr<storage::BlobDataHandle> blob_data_handle =
582 blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid);
583 if (!blob_data_handle) {
584 // The renderer gave us a bad blob UUID.
585 DeliverErrorResponse();
586 return;
588 blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest(
589 blob_data_handle.Pass(), request()->context(), this);
590 blob_request_->Start();
593 response_url_ = response.url;
594 service_worker_response_type_ = response.response_type;
595 CreateResponseHeader(
596 response.status_code, response.status_text, response.headers);
597 load_timing_info_.receive_headers_end = base::TimeTicks::Now();
598 if (!blob_request_)
599 CommitResponseHeader();
602 void ServiceWorkerURLRequestJob::CreateResponseHeader(
603 int status_code,
604 const std::string& status_text,
605 const ServiceWorkerHeaderMap& headers) {
606 // TODO(kinuko): If the response has an identifier to on-disk cache entry,
607 // pull response header from the disk.
608 std::string status_line(
609 base::StringPrintf("HTTP/1.1 %d %s", status_code, status_text.c_str()));
610 status_line.push_back('\0');
611 http_response_headers_ = new net::HttpResponseHeaders(status_line);
612 for (ServiceWorkerHeaderMap::const_iterator it = headers.begin();
613 it != headers.end();
614 ++it) {
615 std::string header;
616 header.reserve(it->first.size() + 2 + it->second.size());
617 header.append(it->first);
618 header.append(": ");
619 header.append(it->second);
620 http_response_headers_->AddHeader(header);
624 void ServiceWorkerURLRequestJob::CommitResponseHeader() {
625 if (!http_response_info_)
626 http_response_info_.reset(new net::HttpResponseInfo());
627 http_response_info_->headers.swap(http_response_headers_);
628 http_response_info_->vary_data = net::HttpVaryData();
629 http_response_info_->metadata = nullptr;
630 NotifyHeadersComplete();
633 void ServiceWorkerURLRequestJob::DeliverErrorResponse() {
634 // TODO(falken): Print an error to the console of the ServiceWorker and of
635 // the requesting page.
636 CreateResponseHeader(
637 500, "Service Worker Response Error", ServiceWorkerHeaderMap());
638 CommitResponseHeader();
641 void ServiceWorkerURLRequestJob::ClearStream() {
642 if (streaming_version_) {
643 streaming_version_->RemoveStreamingURLRequestJob(this);
644 streaming_version_ = nullptr;
646 if (stream_) {
647 stream_->RemoveReadObserver(this);
648 stream_->Abort();
649 stream_ = nullptr;
651 if (!waiting_stream_url_.is_empty()) {
652 StreamRegistry* stream_registry =
653 GetStreamContextForResourceContext(resource_context_)->registry();
654 stream_registry->RemoveRegisterObserver(waiting_stream_url_);
655 stream_registry->AbortPendingStream(waiting_stream_url_);
659 } // namespace content