1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// found in the LICENSE file. 4010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/browser/service_worker/service_worker_read_from_cache_job.h" 6010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <string> 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <vector> 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/debug/trace_event.h" 11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/browser/service_worker/service_worker_context_core.h" 12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/browser/service_worker/service_worker_disk_cache.h" 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/service_worker/service_worker_metrics.h" 14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/base/io_buffer.h" 15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/base/net_errors.h" 16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/http/http_request_headers.h" 17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/http/http_response_headers.h" 18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/http/http_util.h" 19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/url_request/url_request.h" 20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/url_request/url_request_status.h" 21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace content { 23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ServiceWorkerReadFromCacheJob::ServiceWorkerReadFromCacheJob( 25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::URLRequest* request, 26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::NetworkDelegate* network_delegate, 27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::WeakPtr<ServiceWorkerContextCore> context, 28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int64 response_id) 29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) : net::URLRequestJob(request, network_delegate), 30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) context_(context), 31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) response_id_(response_id), 32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) has_been_killed_(false), 33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) weak_factory_(this) { 34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ServiceWorkerReadFromCacheJob::~ServiceWorkerReadFromCacheJob() { 37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ServiceWorkerReadFromCacheJob::Start() { 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "ServiceWorkerReadFromCacheJob::ReadInfo", 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this, 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "URL", request_->url().spec()); 44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!context_) { 45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NotifyStartError(net::URLRequestStatus( 46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::URLRequestStatus::FAILED, net::ERR_FAILED)); 47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Create a response reader and start reading the headers, 51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // we'll continue when thats done. 52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) reader_ = context_->storage()->CreateResponseReader(response_id_); 53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) http_info_io_buffer_ = new HttpResponseInfoIOBuffer; 54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) reader_->ReadInfo( 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci http_info_io_buffer_.get(), 56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::Bind(&ServiceWorkerReadFromCacheJob::OnReadInfoComplete, 57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) weak_factory_.GetWeakPtr())); 58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); 59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ServiceWorkerReadFromCacheJob::Kill() { 62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (has_been_killed_) 63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) weak_factory_.InvalidateWeakPtrs(); 65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) has_been_killed_ = true; 66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) reader_.reset(); 67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) context_.reset(); 68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) http_info_io_buffer_ = NULL; 69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) http_info_.reset(); 70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) range_response_info_.reset(); 71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::URLRequestJob::Kill(); 72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)net::LoadState ServiceWorkerReadFromCacheJob::GetLoadState() const { 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (reader_.get() && reader_->IsReadPending()) 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return net::LOAD_STATE_READING_RESPONSE; 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return net::LOAD_STATE_IDLE; 78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool ServiceWorkerReadFromCacheJob::GetCharset(std::string* charset) { 81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!http_info()) 82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return false; 83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return http_info()->headers->GetCharset(charset); 84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool ServiceWorkerReadFromCacheJob::GetMimeType(std::string* mime_type) const { 87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!http_info()) 88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return false; 89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return http_info()->headers->GetMimeType(mime_type); 90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ServiceWorkerReadFromCacheJob::GetResponseInfo( 93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::HttpResponseInfo* info) { 94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!http_info()) 95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *info = *http_info(); 97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)int ServiceWorkerReadFromCacheJob::GetResponseCode() const { 100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!http_info()) 101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return -1; 102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return http_info()->headers->response_code(); 103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ServiceWorkerReadFromCacheJob::SetExtraRequestHeaders( 106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const net::HttpRequestHeaders& headers) { 107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::string value; 108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::vector<net::HttpByteRange> ranges; 109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &value) || 110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) !net::HttpUtil::ParseRangeHeader(value, &ranges)) { 111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // If multiple ranges are requested, we play dumb and 115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // return the entire response with 200 OK. 116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (ranges.size() == 1U) 117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) range_requested_ = ranges[0]; 118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool ServiceWorkerReadFromCacheJob::ReadRawData( 121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::IOBuffer* buf, 122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int buf_size, 123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int *bytes_read) { 124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_NE(buf_size, 0); 125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(bytes_read); 126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(!reader_->IsReadPending()); 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "ServiceWorkerReadFromCacheJob::ReadRawData", 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this, 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "URL", request_->url().spec()); 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) reader_->ReadData( 132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) buf, buf_size, base::Bind(&ServiceWorkerReadFromCacheJob::OnReadComplete, 133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) weak_factory_.GetWeakPtr())); 134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); 135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return false; 136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const net::HttpResponseInfo* ServiceWorkerReadFromCacheJob::http_info() const { 139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!http_info_) 140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return NULL; 141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (range_response_info_) 142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return range_response_info_.get(); 143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return http_info_.get(); 144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ServiceWorkerReadFromCacheJob::OnReadInfoComplete(int result) { 147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_refptr<ServiceWorkerReadFromCacheJob> protect(this); 148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!http_info_io_buffer_->http_info) { 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_LT(result, 0); 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ServiceWorkerMetrics::CountReadResponseResult( 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ServiceWorkerMetrics::READ_HEADERS_ERROR); 152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); 153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_GE(result, 0); 156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status 157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) http_info_.reset(http_info_io_buffer_->http_info.release()); 158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (is_range_request()) 159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) SetupRangeResponse(http_info_io_buffer_->response_data_size); 160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) http_info_io_buffer_ = NULL; 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TRACE_EVENT_ASYNC_END1("ServiceWorker", 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "ServiceWorkerReadFromCacheJob::ReadInfo", 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this, 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Result", result); 165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NotifyHeadersComplete(); 166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ServiceWorkerReadFromCacheJob::SetupRangeResponse(int resource_size) { 169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(is_range_request() && http_info_.get() && reader_.get()); 170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (resource_size < 0 || !range_requested_.ComputeBounds(resource_size)) { 171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) range_requested_ = net::HttpByteRange(); 172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(range_requested_.IsValid()); 176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int offset = static_cast<int>(range_requested_.first_byte_position()); 177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int length = static_cast<int>(range_requested_.last_byte_position() - 178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) range_requested_.first_byte_position() + 1); 179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Tell the reader about the range to read. 181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) reader_->SetReadRange(offset, length); 182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Make a copy of the full response headers and fix them up 184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // for the range we'll be returning. 185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) range_response_info_.reset(new net::HttpResponseInfo(*http_info_)); 186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::HttpResponseHeaders* headers = range_response_info_->headers.get(); 187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) headers->UpdateWithNewRange( 188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) range_requested_, resource_size, true /* replace status line */); 189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ServiceWorkerReadFromCacheJob::OnReadComplete(int result) { 192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ServiceWorkerMetrics::ReadResponseResult check_result; 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (result == 0) { 194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch check_result = ServiceWorkerMetrics::READ_OK; 195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NotifyDone(net::URLRequestStatus()); 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (result < 0) { 197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch check_result = ServiceWorkerMetrics::READ_DATA_ERROR; 198010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch check_result = ServiceWorkerMetrics::READ_OK; 201010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ServiceWorkerMetrics::CountReadResponseResult(check_result); 204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NotifyReadComplete(result); 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TRACE_EVENT_ASYNC_END1("ServiceWorker", 2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "ServiceWorkerReadFromCacheJob::ReadRawData", 2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this, 2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Result", result); 209010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 210010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace content 212