Chromium Code Reviews| Index: content/browser/service_worker/service_worker_write_to_cache_job.cc |
| diff --git a/content/browser/service_worker/service_worker_write_to_cache_job.cc b/content/browser/service_worker/service_worker_write_to_cache_job.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..6a7f9d74892dac4c7d6b4018e2e319f6b26915e6 |
| --- /dev/null |
| +++ b/content/browser/service_worker/service_worker_write_to_cache_job.cc |
| @@ -0,0 +1,263 @@ |
| +// Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/service_worker/service_worker_write_to_cache_job.h" |
| + |
| +#include "content/browser/service_worker/service_worker_context_core.h" |
| +#include "content/browser/service_worker/service_worker_disk_cache.h" |
| +#include "net/base/io_buffer.h" |
| +#include "net/base/net_errors.h" |
| +#include "net/http/http_request_headers.h" |
| +#include "net/http/http_response_headers.h" |
| +#include "net/http/http_util.h" |
| +#include "net/url_request/url_request.h" |
| +#include "net/url_request/url_request_context.h" |
| +#include "net/url_request/url_request_status.h" |
| + |
| +namespace content { |
| + |
| +ServiceWorkerWriteToCacheJob::ServiceWorkerWriteToCacheJob( |
| + net::URLRequest* request, |
| + net::NetworkDelegate* network_delegate, |
| + base::WeakPtr<ServiceWorkerContextCore> context, |
| + ServiceWorkerVersion* version, |
| + int64 response_id) |
| + : net::URLRequestJob(request, network_delegate), |
| + context_(context), |
| + version_(version), |
| + response_id_(response_id), |
| + has_been_killed_(false), |
| + weak_factory_(this) { |
| + InitNetRequest(); |
| +} |
| + |
| +ServiceWorkerWriteToCacheJob::~ServiceWorkerWriteToCacheJob() { |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::Start() { |
| + if (!context_) { |
| + NotifyStartError(net::URLRequestStatus( |
| + net::URLRequestStatus::FAILED, net::ERR_FAILED)); |
| + return; |
| + } |
| + StartNetRequest(); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::Kill() { |
| + if (has_been_killed_) |
| + return; |
| + weak_factory_.InvalidateWeakPtrs(); |
| + has_been_killed_ = true; |
| + net_request_.reset(); |
| + writer_.reset(); |
| + context_.reset(); |
| + net::URLRequestJob::Kill(); |
| +} |
| + |
| +net::LoadState ServiceWorkerWriteToCacheJob::GetLoadState() const { |
| + NOTIMPLEMENTED(); |
| + return net::LOAD_STATE_WAITING_FOR_APPCACHE; |
| +} |
| + |
| +bool ServiceWorkerWriteToCacheJob::GetCharset(std::string* charset) { |
| + if (!http_info()) |
| + return false; |
| + return http_info()->headers->GetCharset(charset); |
| +} |
| + |
| +bool ServiceWorkerWriteToCacheJob::GetMimeType(std::string* mime_type) const { |
| + if (!http_info()) |
| + return false; |
| + return http_info()->headers->GetMimeType(mime_type); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::GetResponseInfo( |
| + net::HttpResponseInfo* info) { |
| + if (!http_info()) |
| + return; |
| + *info = *http_info(); |
| +} |
| + |
| +int ServiceWorkerWriteToCacheJob::GetResponseCode() const { |
| + if (!http_info()) |
| + return -1; |
| + return http_info()->headers->response_code(); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::SetExtraRequestHeaders( |
| + const net::HttpRequestHeaders& headers) { |
| + // TODO(michaeln): how does this related to request->extra_headers() on input??? |
| + std::string value; |
| + if (headers.GetHeader(net::HttpRequestHeaders::kRange, &value)) { |
| + // todo error out |
| + return; |
| + } |
| + net_request_->SetExtraRequestHeaders(headers); |
| +} |
| + |
| +bool ServiceWorkerWriteToCacheJob::ReadRawData( |
| + net::IOBuffer* buf, |
| + int buf_size, |
| + int *bytes_read) { |
| + return ReadNetData(buf, buf_size, bytes_read); |
| +} |
| + |
| +const net::HttpResponseInfo* ServiceWorkerWriteToCacheJob::http_info() const { |
| + return http_info_.get(); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::InitNetRequest() { |
| + DCHECK(request()); |
| + net_request_ = request()->context()->CreateRequest( |
| + request()->url(), |
| + request()->priority(), |
| + this, |
| + NULL); // TODO(michaeln): request()->cookie_store() |
| + net_request_->set_first_party_for_cookies( |
| + request()->first_party_for_cookies()); |
| + net_request_->SetReferrer(request()->referrer()); |
| + net_request_->SetExtraRequestHeaders(request()->extra_request_headers()); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::StartNetRequest() { |
| + net_request_->Start(); // We'll continue in OnResponseStarted. |
| +} |
| + |
| +bool ServiceWorkerWriteToCacheJob::ReadNetData( |
| + net::IOBuffer* buf, |
| + int buf_size, |
| + int *bytes_read) { |
| + DCHECK_GT(buf_size, 0); |
| + DCHECK(bytes_read); |
| + io_buffer_ = buf; |
| + io_buffer_size_ = buf_size; |
| + int rv = net_request_->Read(buf, buf_size, bytes_read); |
| + if (rv == net::ERR_IO_PENDING) { |
| + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); |
| + return false; |
| + } |
| + if (rv < 0) { |
| + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, rv)); |
| + return false; |
| + } |
| + if (rv == 0) { |
| + // done with all |
| + NotifyReadComplete(0); |
| + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0)); |
| + version_->NotifyMainScriptCacheResult(true); // todo: all cases |
|
michaeln
2014/05/07 05:46:05
Do this only for the main script, not imports.
|
| + return true; // ? |
| + } |
| + WriteDataToCache(rv); |
| + return false; |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::WriteHeadersToCache() { |
| + if (!context_) { |
| + // todo: error out |
| + return; |
| + } |
| + writer_ = context_->storage()->CreateResponseWriter(response_id_); |
| + info_buffer_ = new HttpResponseInfoIOBuffer( |
| + new net::HttpResponseInfo(net_request_->response_info())); |
| + writer_->WriteInfo( |
| + info_buffer_, |
| + base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete, |
| + weak_factory_.GetWeakPtr())); |
| + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete(int result) { |
| + SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status |
| + if (result < 0) { |
| + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); |
| + return; |
| + } |
| + http_info_.reset(info_buffer_->http_info.release()); |
| + info_buffer_ = NULL; |
| + NotifyHeadersComplete(); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::WriteDataToCache(int amount_to_write) { |
| + DCHECK_NE(0, amount_to_write); |
| + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); |
| + writer_->WriteData( |
| + io_buffer_, amount_to_write, |
| + base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteDataComplete, |
| + weak_factory_.GetWeakPtr())); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::OnWriteDataComplete(int result) { |
| + DCHECK_NE(0, result); |
| + if (!context_) { |
| + // todo: error out |
| + return; |
| + } |
| + if (result < 0) { |
| + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); |
| + return; |
| + } |
| + SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status |
| + NotifyReadComplete(result); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::OnReceivedRedirect( |
| + net::URLRequest* request, |
| + const GURL& new_url, |
| + bool* defer_redirect) { |
| + // todo: error out for now - maybe NotifyHeadersComplete later |
| + *defer_redirect = true; |
| + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, -1)); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::OnAuthRequired( |
| + net::URLRequest* request, |
| + net::AuthChallengeInfo* auth_info) { |
| + // todo: error out for now - NotifyHeadersComplete later |
| + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, -1)); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::OnCertificateRequested( |
| + net::URLRequest* request, |
| + net::SSLCertRequestInfo* cert_request_info) { |
| + // todo: NotifyCertificateRequested (error out for now?) |
| + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, -1)); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob:: OnSSLCertificateError( |
| + net::URLRequest* request, |
| + const net::SSLInfo& ssl_info, |
| + bool fatal) { |
| + // todo: NotifySSLCertificateError (error out for now?) |
| + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, -1)); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::OnBeforeNetworkStart( |
| + net::URLRequest* request, |
| + bool* defer) { |
| + DCHECK_EQ(net_request_, request); |
| + NotifyBeforeNetworkStart(defer); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::OnResponseStarted( |
| + net::URLRequest* request) { |
| + DCHECK_EQ(net_request_, request); |
| + if (!request->status().is_success() || |
| + request->GetResponseCode() / 100 != 2) { |
| + NotifyDone(request->status()); |
| + return; |
| + } |
| + WriteHeadersToCache(); |
| +} |
| + |
| +void ServiceWorkerWriteToCacheJob::OnReadCompleted( |
| + net::URLRequest* request, |
| + int bytes_read) { |
| + DCHECK_EQ(net_request_, request); |
| + if (net_request_->status().is_success() && bytes_read > 0) { |
| + WriteDataToCache(bytes_read); |
| + return; |
| + } |
| +} |
| + |
| +} // namespace content |