Index: webkit/browser/appcache/appcache_url_request_job.cc |
diff --git a/webkit/browser/appcache/appcache_url_request_job.cc b/webkit/browser/appcache/appcache_url_request_job.cc |
deleted file mode 100644 |
index 2cdcb779a50bf4689d49ba3832ea5b04fc7e0731..0000000000000000000000000000000000000000 |
--- a/webkit/browser/appcache/appcache_url_request_job.cc |
+++ /dev/null |
@@ -1,449 +0,0 @@ |
-// Copyright (c) 2012 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 "webkit/browser/appcache/appcache_url_request_job.h" |
- |
-#include <vector> |
- |
-#include "base/bind.h" |
-#include "base/bind_helpers.h" |
-#include "base/command_line.h" |
-#include "base/compiler_specific.h" |
-#include "base/message_loop/message_loop.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/stringprintf.h" |
-#include "net/base/io_buffer.h" |
-#include "net/base/net_errors.h" |
-#include "net/base/net_log.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_status.h" |
-#include "webkit/browser/appcache/appcache.h" |
-#include "webkit/browser/appcache/appcache_group.h" |
-#include "webkit/browser/appcache/appcache_histograms.h" |
-#include "webkit/browser/appcache/appcache_host.h" |
-#include "webkit/browser/appcache/appcache_service_impl.h" |
- |
-namespace appcache { |
- |
-AppCacheURLRequestJob::AppCacheURLRequestJob( |
- net::URLRequest* request, |
- net::NetworkDelegate* network_delegate, |
- AppCacheStorage* storage, |
- AppCacheHost* host, |
- bool is_main_resource) |
- : net::URLRequestJob(request, network_delegate), |
- host_(host), |
- storage_(storage), |
- has_been_started_(false), has_been_killed_(false), |
- delivery_type_(AWAITING_DELIVERY_ORDERS), |
- group_id_(0), cache_id_(kAppCacheNoCacheId), is_fallback_(false), |
- is_main_resource_(is_main_resource), |
- cache_entry_not_found_(false), |
- weak_factory_(this) { |
- DCHECK(storage_); |
-} |
- |
-void AppCacheURLRequestJob::DeliverAppCachedResponse( |
- const GURL& manifest_url, int64 group_id, int64 cache_id, |
- const AppCacheEntry& entry, bool is_fallback) { |
- DCHECK(!has_delivery_orders()); |
- DCHECK(entry.has_response_id()); |
- delivery_type_ = APPCACHED_DELIVERY; |
- manifest_url_ = manifest_url; |
- group_id_ = group_id; |
- cache_id_ = cache_id; |
- entry_ = entry; |
- is_fallback_ = is_fallback; |
- MaybeBeginDelivery(); |
-} |
- |
-void AppCacheURLRequestJob::DeliverNetworkResponse() { |
- DCHECK(!has_delivery_orders()); |
- delivery_type_ = NETWORK_DELIVERY; |
- storage_ = NULL; // not needed |
- MaybeBeginDelivery(); |
-} |
- |
-void AppCacheURLRequestJob::DeliverErrorResponse() { |
- DCHECK(!has_delivery_orders()); |
- delivery_type_ = ERROR_DELIVERY; |
- storage_ = NULL; // not needed |
- MaybeBeginDelivery(); |
-} |
- |
-void AppCacheURLRequestJob::MaybeBeginDelivery() { |
- if (has_been_started() && has_delivery_orders()) { |
- // Start asynchronously so that all error reporting and data |
- // callbacks happen as they would for network requests. |
- base::MessageLoop::current()->PostTask( |
- FROM_HERE, |
- base::Bind(&AppCacheURLRequestJob::BeginDelivery, |
- weak_factory_.GetWeakPtr())); |
- } |
-} |
- |
-void AppCacheURLRequestJob::BeginDelivery() { |
- DCHECK(has_delivery_orders() && has_been_started()); |
- |
- if (has_been_killed()) |
- return; |
- |
- switch (delivery_type_) { |
- case NETWORK_DELIVERY: |
- AppCacheHistograms::AddNetworkJobStartDelaySample( |
- base::TimeTicks::Now() - start_time_tick_); |
- // To fallthru to the network, we restart the request which will |
- // cause a new job to be created to retrieve the resource from the |
- // network. Our caller is responsible for arranging to not re-intercept |
- // the same request. |
- NotifyRestartRequired(); |
- break; |
- |
- case ERROR_DELIVERY: |
- AppCacheHistograms::AddErrorJobStartDelaySample( |
- base::TimeTicks::Now() - start_time_tick_); |
- request()->net_log().AddEvent( |
- net::NetLog::TYPE_APPCACHE_DELIVERING_ERROR_RESPONSE); |
- NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, |
- net::ERR_FAILED)); |
- break; |
- |
- case APPCACHED_DELIVERY: |
- if (entry_.IsExecutable()) { |
- BeginExecutableHandlerDelivery(); |
- return; |
- } |
- AppCacheHistograms::AddAppCacheJobStartDelaySample( |
- base::TimeTicks::Now() - start_time_tick_); |
- request()->net_log().AddEvent( |
- is_fallback_ ? |
- net::NetLog::TYPE_APPCACHE_DELIVERING_FALLBACK_RESPONSE : |
- net::NetLog::TYPE_APPCACHE_DELIVERING_CACHED_RESPONSE); |
- storage_->LoadResponseInfo( |
- manifest_url_, group_id_, entry_.response_id(), this); |
- break; |
- |
- default: |
- NOTREACHED(); |
- break; |
- } |
-} |
- |
-void AppCacheURLRequestJob::BeginExecutableHandlerDelivery() { |
- DCHECK(CommandLine::ForCurrentProcess()-> |
- HasSwitch(kEnableExecutableHandlers)); |
- if (!storage_->service()->handler_factory()) { |
- BeginErrorDelivery("missing handler factory"); |
- return; |
- } |
- |
- request()->net_log().AddEvent( |
- net::NetLog::TYPE_APPCACHE_DELIVERING_EXECUTABLE_RESPONSE); |
- |
- // We defer job delivery until the executable handler is spun up and |
- // provides a response. The sequence goes like this... |
- // |
- // 1. First we load the cache. |
- // 2. Then if the handler is not spun up, we load the script resource which |
- // is needed to spin it up. |
- // 3. Then we ask then we ask the handler to compute a response. |
- // 4. Finally we deilver that response to the caller. |
- storage_->LoadCache(cache_id_, this); |
-} |
- |
-void AppCacheURLRequestJob::OnCacheLoaded(AppCache* cache, int64 cache_id) { |
- DCHECK_EQ(cache_id_, cache_id); |
- DCHECK(!has_been_killed()); |
- |
- if (!cache) { |
- BeginErrorDelivery("cache load failed"); |
- return; |
- } |
- |
- // Keep references to ensure they don't go out of scope until job completion. |
- cache_ = cache; |
- group_ = cache->owning_group(); |
- |
- // If the handler is spun up, ask it to compute a response. |
- AppCacheExecutableHandler* handler = |
- cache->GetExecutableHandler(entry_.response_id()); |
- if (handler) { |
- InvokeExecutableHandler(handler); |
- return; |
- } |
- |
- // Handler is not spun up yet, load the script resource to do that. |
- // NOTE: This is not ideal since multiple jobs may be doing this, |
- // concurrently but close enough for now, the first to load the script |
- // will win. |
- |
- // Read the script data, truncating if its too large. |
- // NOTE: we just issue one read and don't bother chaining if the resource |
- // is very (very) large, close enough for now. |
- const int64 kLimit = 500 * 1000; |
- handler_source_buffer_ = new net::GrowableIOBuffer(); |
- handler_source_buffer_->SetCapacity(kLimit); |
- handler_source_reader_.reset(storage_->CreateResponseReader( |
- manifest_url_, group_id_, entry_.response_id())); |
- handler_source_reader_->ReadData( |
- handler_source_buffer_.get(), |
- kLimit, |
- base::Bind(&AppCacheURLRequestJob::OnExecutableSourceLoaded, |
- base::Unretained(this))); |
-} |
- |
-void AppCacheURLRequestJob::OnExecutableSourceLoaded(int result) { |
- DCHECK(!has_been_killed()); |
- handler_source_reader_.reset(); |
- if (result < 0) { |
- BeginErrorDelivery("script source load failed"); |
- return; |
- } |
- |
- handler_source_buffer_->SetCapacity(result); // Free up some memory. |
- |
- AppCacheExecutableHandler* handler = cache_->GetOrCreateExecutableHandler( |
- entry_.response_id(), handler_source_buffer_.get()); |
- handler_source_buffer_ = NULL; // not needed anymore |
- if (handler) { |
- InvokeExecutableHandler(handler); |
- return; |
- } |
- |
- BeginErrorDelivery("factory failed to produce a handler"); |
-} |
- |
-void AppCacheURLRequestJob::InvokeExecutableHandler( |
- AppCacheExecutableHandler* handler) { |
- handler->HandleRequest( |
- request(), |
- base::Bind(&AppCacheURLRequestJob::OnExecutableResponseCallback, |
- weak_factory_.GetWeakPtr())); |
-} |
- |
-void AppCacheURLRequestJob::OnExecutableResponseCallback( |
- const AppCacheExecutableHandler::Response& response) { |
- DCHECK(!has_been_killed()); |
- if (response.use_network) { |
- delivery_type_ = NETWORK_DELIVERY; |
- storage_ = NULL; |
- BeginDelivery(); |
- return; |
- } |
- |
- if (!response.cached_resource_url.is_empty()) { |
- AppCacheEntry* entry_ptr = cache_->GetEntry(response.cached_resource_url); |
- if (entry_ptr && !entry_ptr->IsExecutable()) { |
- entry_ = *entry_ptr; |
- BeginDelivery(); |
- return; |
- } |
- } |
- |
- if (!response.redirect_url.is_empty()) { |
- // TODO(michaeln): playback a redirect |
- // response_headers_(new HttpResponseHeaders(response_headers)), |
- // fallthru for now to deliver an error |
- } |
- |
- // Otherwise, return an error. |
- BeginErrorDelivery("handler returned an invalid response"); |
-} |
- |
-void AppCacheURLRequestJob::BeginErrorDelivery(const char* message) { |
- if (host_) |
- host_->frontend()->OnLogMessage(host_->host_id(), APPCACHE_LOG_ERROR, |
- message); |
- delivery_type_ = ERROR_DELIVERY; |
- storage_ = NULL; |
- BeginDelivery(); |
-} |
- |
-AppCacheURLRequestJob::~AppCacheURLRequestJob() { |
- if (storage_) |
- storage_->CancelDelegateCallbacks(this); |
-} |
- |
-void AppCacheURLRequestJob::OnResponseInfoLoaded( |
- AppCacheResponseInfo* response_info, int64 response_id) { |
- DCHECK(is_delivering_appcache_response()); |
- scoped_refptr<AppCacheURLRequestJob> protect(this); |
- if (response_info) { |
- info_ = response_info; |
- reader_.reset(storage_->CreateResponseReader( |
- manifest_url_, group_id_, entry_.response_id())); |
- |
- if (is_range_request()) |
- SetupRangeResponse(); |
- |
- NotifyHeadersComplete(); |
- } else { |
- if (storage_->service()->storage() == storage_) { |
- // A resource that is expected to be in the appcache is missing. |
- // See http://code.google.com/p/chromium/issues/detail?id=50657 |
- // Instead of failing the request, we restart the request. The retry |
- // attempt will fallthru to the network instead of trying to load |
- // from the appcache. |
- storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_, |
- entry_.response_id()); |
- AppCacheHistograms::CountResponseRetrieval( |
- false, is_main_resource_, manifest_url_.GetOrigin()); |
- } |
- cache_entry_not_found_ = true; |
- NotifyRestartRequired(); |
- } |
-} |
- |
-const net::HttpResponseInfo* AppCacheURLRequestJob::http_info() const { |
- if (!info_.get()) |
- return NULL; |
- if (range_response_info_) |
- return range_response_info_.get(); |
- return info_->http_response_info(); |
-} |
- |
-void AppCacheURLRequestJob::SetupRangeResponse() { |
- DCHECK(is_range_request() && info_.get() && reader_.get() && |
- is_delivering_appcache_response()); |
- int resource_size = static_cast<int>(info_->response_data_size()); |
- if (resource_size < 0 || !range_requested_.ComputeBounds(resource_size)) { |
- range_requested_ = net::HttpByteRange(); |
- return; |
- } |
- |
- DCHECK(range_requested_.IsValid()); |
- int offset = static_cast<int>(range_requested_.first_byte_position()); |
- int length = static_cast<int>(range_requested_.last_byte_position() - |
- range_requested_.first_byte_position() + 1); |
- |
- // Tell the reader about the range to read. |
- reader_->SetReadRange(offset, length); |
- |
- // Make a copy of the full response headers and fix them up |
- // for the range we'll be returning. |
- range_response_info_.reset( |
- new net::HttpResponseInfo(*info_->http_response_info())); |
- net::HttpResponseHeaders* headers = range_response_info_->headers.get(); |
- headers->UpdateWithNewRange( |
- range_requested_, resource_size, true /* replace status line */); |
-} |
- |
-void AppCacheURLRequestJob::OnReadComplete(int result) { |
- DCHECK(is_delivering_appcache_response()); |
- if (result == 0) { |
- NotifyDone(net::URLRequestStatus()); |
- AppCacheHistograms::CountResponseRetrieval( |
- true, is_main_resource_, manifest_url_.GetOrigin()); |
- } else if (result < 0) { |
- if (storage_->service()->storage() == storage_) { |
- storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_, |
- entry_.response_id()); |
- } |
- NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); |
- AppCacheHistograms::CountResponseRetrieval( |
- false, is_main_resource_, manifest_url_.GetOrigin()); |
- } else { |
- SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status |
- } |
- NotifyReadComplete(result); |
-} |
- |
-// net::URLRequestJob overrides ------------------------------------------------ |
- |
-void AppCacheURLRequestJob::Start() { |
- DCHECK(!has_been_started()); |
- has_been_started_ = true; |
- start_time_tick_ = base::TimeTicks::Now(); |
- MaybeBeginDelivery(); |
-} |
- |
-void AppCacheURLRequestJob::Kill() { |
- if (!has_been_killed_) { |
- has_been_killed_ = true; |
- reader_.reset(); |
- handler_source_reader_.reset(); |
- if (storage_) { |
- storage_->CancelDelegateCallbacks(this); |
- storage_ = NULL; |
- } |
- host_ = NULL; |
- info_ = NULL; |
- cache_ = NULL; |
- group_ = NULL; |
- range_response_info_.reset(); |
- net::URLRequestJob::Kill(); |
- weak_factory_.InvalidateWeakPtrs(); |
- } |
-} |
- |
-net::LoadState AppCacheURLRequestJob::GetLoadState() const { |
- if (!has_been_started()) |
- return net::LOAD_STATE_IDLE; |
- if (!has_delivery_orders()) |
- return net::LOAD_STATE_WAITING_FOR_APPCACHE; |
- if (delivery_type_ != APPCACHED_DELIVERY) |
- return net::LOAD_STATE_IDLE; |
- if (!info_.get()) |
- return net::LOAD_STATE_WAITING_FOR_APPCACHE; |
- if (reader_.get() && reader_->IsReadPending()) |
- return net::LOAD_STATE_READING_RESPONSE; |
- return net::LOAD_STATE_IDLE; |
-} |
- |
-bool AppCacheURLRequestJob::GetMimeType(std::string* mime_type) const { |
- if (!http_info()) |
- return false; |
- return http_info()->headers->GetMimeType(mime_type); |
-} |
- |
-bool AppCacheURLRequestJob::GetCharset(std::string* charset) { |
- if (!http_info()) |
- return false; |
- return http_info()->headers->GetCharset(charset); |
-} |
- |
-void AppCacheURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { |
- if (!http_info()) |
- return; |
- *info = *http_info(); |
-} |
- |
-int AppCacheURLRequestJob::GetResponseCode() const { |
- if (!http_info()) |
- return -1; |
- return http_info()->headers->response_code(); |
-} |
- |
-bool AppCacheURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size, |
- int *bytes_read) { |
- DCHECK(is_delivering_appcache_response()); |
- DCHECK_NE(buf_size, 0); |
- DCHECK(bytes_read); |
- DCHECK(!reader_->IsReadPending()); |
- reader_->ReadData( |
- buf, buf_size, base::Bind(&AppCacheURLRequestJob::OnReadComplete, |
- base::Unretained(this))); |
- SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); |
- return false; |
-} |
- |
-void AppCacheURLRequestJob::SetExtraRequestHeaders( |
- const net::HttpRequestHeaders& headers) { |
- std::string value; |
- std::vector<net::HttpByteRange> ranges; |
- if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &value) || |
- !net::HttpUtil::ParseRangeHeader(value, &ranges)) { |
- return; |
- } |
- |
- // If multiple ranges are requested, we play dumb and |
- // return the entire response with 200 OK. |
- if (ranges.size() == 1U) |
- range_requested_ = ranges[0]; |
-} |
- |
-} // namespace appcache |