| 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
|
|
|