service_worker_read_from_cache_job.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file. 4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_read_from_cache_job.h" 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_context_core.h" 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/service_worker/service_worker_disk_cache.h" 9a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "content/browser/service_worker/service_worker_histograms.h" 10a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "net/base/io_buffer.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/net_errors.h" 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/http/http_request_headers.h" 1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/http/http_response_headers.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/http/http_util.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_request.h" 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_request_status.h" 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace content { 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ServiceWorkerReadFromCacheJob::ServiceWorkerReadFromCacheJob( 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::URLRequest* request, 22a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch net::NetworkDelegate* network_delegate, 23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch base::WeakPtr<ServiceWorkerContextCore> context, 24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch int64 response_id) 25a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch : net::URLRequestJob(request, network_delegate), 26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch context_(context), 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) response_id_(response_id), 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) has_been_killed_(false), 2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) weak_factory_(this) { 3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)ServiceWorkerReadFromCacheJob::~ServiceWorkerReadFromCacheJob() { 3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ServiceWorkerReadFromCacheJob::Start() { 3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!context_) { 3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) NotifyStartError(net::URLRequestStatus( 3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) net::URLRequestStatus::FAILED, net::ERR_FAILED)); 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Create a response reader and start reading the headers, 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // we'll continue when thats done. 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) reader_ = context_->storage()->CreateResponseReader(response_id_); 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) http_info_io_buffer_ = new HttpResponseInfoIOBuffer; 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) reader_->ReadInfo( 47 http_info_io_buffer_, 48 base::Bind(&ServiceWorkerReadFromCacheJob::OnReadInfoComplete, 49 weak_factory_.GetWeakPtr())); 50 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); 51} 52 53void ServiceWorkerReadFromCacheJob::Kill() { 54 if (has_been_killed_) 55 return; 56 weak_factory_.InvalidateWeakPtrs(); 57 has_been_killed_ = true; 58 reader_.reset(); 59 context_.reset(); 60 http_info_io_buffer_ = NULL; 61 http_info_.reset(); 62 range_response_info_.reset(); 63 net::URLRequestJob::Kill(); 64} 65 66net::LoadState ServiceWorkerReadFromCacheJob::GetLoadState() const { 67 if (reader_.get() && reader_->IsReadPending()) 68 return net::LOAD_STATE_READING_RESPONSE; 69 return net::LOAD_STATE_IDLE; 70} 71 72bool ServiceWorkerReadFromCacheJob::GetCharset(std::string* charset) { 73 if (!http_info()) 74 return false; 75 return http_info()->headers->GetCharset(charset); 76} 77 78bool ServiceWorkerReadFromCacheJob::GetMimeType(std::string* mime_type) const { 79 if (!http_info()) 80 return false; 81 return http_info()->headers->GetMimeType(mime_type); 82} 83 84void ServiceWorkerReadFromCacheJob::GetResponseInfo( 85 net::HttpResponseInfo* info) { 86 if (!http_info()) 87 return; 88 *info = *http_info(); 89} 90 91int ServiceWorkerReadFromCacheJob::GetResponseCode() const { 92 if (!http_info()) 93 return -1; 94 return http_info()->headers->response_code(); 95} 96 97void ServiceWorkerReadFromCacheJob::SetExtraRequestHeaders( 98 const net::HttpRequestHeaders& headers) { 99 std::string value; 100 std::vector<net::HttpByteRange> ranges; 101 if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &value) || 102 !net::HttpUtil::ParseRangeHeader(value, &ranges)) { 103 return; 104 } 105 106 // If multiple ranges are requested, we play dumb and 107 // return the entire response with 200 OK. 108 if (ranges.size() == 1U) 109 range_requested_ = ranges[0]; 110} 111 112bool ServiceWorkerReadFromCacheJob::ReadRawData( 113 net::IOBuffer* buf, 114 int buf_size, 115 int *bytes_read) { 116 DCHECK_NE(buf_size, 0); 117 DCHECK(bytes_read); 118 DCHECK(!reader_->IsReadPending()); 119 reader_->ReadData( 120 buf, buf_size, base::Bind(&ServiceWorkerReadFromCacheJob::OnReadComplete, 121 weak_factory_.GetWeakPtr())); 122 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); 123 return false; 124} 125 126const net::HttpResponseInfo* ServiceWorkerReadFromCacheJob::http_info() const { 127 if (!http_info_) 128 return NULL; 129 if (range_response_info_) 130 return range_response_info_.get(); 131 return http_info_.get(); 132} 133 134void ServiceWorkerReadFromCacheJob::OnReadInfoComplete(int result) { 135 scoped_refptr<ServiceWorkerReadFromCacheJob> protect(this); 136 if (!http_info_io_buffer_->http_info) { 137 DCHECK(result < 0); 138 ServiceWorkerHistograms::CountReadResponseResult( 139 ServiceWorkerHistograms::READ_HEADERS_ERROR); 140 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); 141 return; 142 } 143 DCHECK(result >= 0); 144 SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status 145 http_info_.reset(http_info_io_buffer_->http_info.release()); 146 if (is_range_request()) 147 SetupRangeResponse(http_info_io_buffer_->response_data_size); 148 http_info_io_buffer_ = NULL; 149 NotifyHeadersComplete(); 150} 151 152void ServiceWorkerReadFromCacheJob::SetupRangeResponse(int resource_size) { 153 DCHECK(is_range_request() && http_info_.get() && reader_.get()); 154 if (resource_size < 0 || !range_requested_.ComputeBounds(resource_size)) { 155 range_requested_ = net::HttpByteRange(); 156 return; 157 } 158 159 DCHECK(range_requested_.IsValid()); 160 int offset = static_cast<int>(range_requested_.first_byte_position()); 161 int length = static_cast<int>(range_requested_.last_byte_position() - 162 range_requested_.first_byte_position() + 1); 163 164 // Tell the reader about the range to read. 165 reader_->SetReadRange(offset, length); 166 167 // Make a copy of the full response headers and fix them up 168 // for the range we'll be returning. 169 range_response_info_.reset(new net::HttpResponseInfo(*http_info_)); 170 net::HttpResponseHeaders* headers = range_response_info_->headers.get(); 171 headers->UpdateWithNewRange( 172 range_requested_, resource_size, true /* replace status line */); 173} 174 175void ServiceWorkerReadFromCacheJob::OnReadComplete(int result) { 176 ServiceWorkerHistograms::ReadResponseResult check_result; 177 if (result == 0) { 178 check_result = ServiceWorkerHistograms::READ_OK; 179 NotifyDone(net::URLRequestStatus()); 180 } else if (result < 0) { 181 check_result = ServiceWorkerHistograms::READ_DATA_ERROR; 182 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); 183 } else { 184 check_result = ServiceWorkerHistograms::READ_OK; 185 SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status 186 } 187 ServiceWorkerHistograms::CountReadResponseResult(check_result); 188 NotifyReadComplete(result); 189} 190 191} // namespace content 192