15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache_url_request_job.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <vector>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/command_line.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "net/base/io_buffer.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_headers.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_util.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h"
247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "webkit/browser/appcache/appcache.h"
257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "webkit/browser/appcache/appcache_group.h"
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache_histograms.h"
277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "webkit/browser/appcache/appcache_host.h"
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache_service.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace appcache {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppCacheURLRequestJob::AppCacheURLRequestJob(
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::NetworkDelegate* network_delegate,
357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    AppCacheStorage* storage,
367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    AppCacheHost* host)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : net::URLRequestJob(request, network_delegate),
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      host_(host),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      storage_(storage),
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_been_started_(false), has_been_killed_(false),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delivery_type_(AWAITING_DELIVERY_ORDERS),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      group_id_(0), cache_id_(kNoCacheId), is_fallback_(false),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cache_entry_not_found_(false),
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(storage_);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::DeliverAppCachedResponse(
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& manifest_url, int64 group_id, int64 cache_id,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AppCacheEntry& entry, bool is_fallback) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!has_delivery_orders());
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry.has_response_id());
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delivery_type_ = APPCACHED_DELIVERY;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest_url_ = manifest_url;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  group_id_ = group_id;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_id_ = cache_id;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry_ = entry;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_fallback_ = is_fallback;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MaybeBeginDelivery();
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::DeliverNetworkResponse() {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!has_delivery_orders());
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delivery_type_ = NETWORK_DELIVERY;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  storage_ = NULL;  // not needed
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MaybeBeginDelivery();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::DeliverErrorResponse() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!has_delivery_orders());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delivery_type_ = ERROR_DELIVERY;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  storage_ = NULL;  // not needed
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MaybeBeginDelivery();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::MaybeBeginDelivery() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_been_started() && has_delivery_orders()) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start asynchronously so that all error reporting and data
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // callbacks happen as they would for network requests.
80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AppCacheURLRequestJob::BeginDelivery,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_factory_.GetWeakPtr()));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::BeginDelivery() {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(has_delivery_orders() && has_been_started());
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_been_killed())
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (delivery_type_) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NETWORK_DELIVERY:
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AppCacheHistograms::AddNetworkJobStartDelaySample(
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::TimeTicks::Now() - start_time_tick_);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // To fallthru to the network, we restart the request which will
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // cause a new job to be created to retrieve the resource from the
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // network. Our caller is responsible for arranging to not re-intercept
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the same request.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NotifyRestartRequired();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ERROR_DELIVERY:
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AppCacheHistograms::AddErrorJobStartDelaySample(
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::TimeTicks::Now() - start_time_tick_);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request()->net_log().AddEvent(
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_APPCACHE_DELIVERING_ERROR_RESPONSE);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             net::ERR_FAILED));
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case APPCACHED_DELIVERY:
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (entry_.IsExecutable()) {
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        BeginExecutableHandlerDelivery();
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AppCacheHistograms::AddAppCacheJobStartDelaySample(
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::TimeTicks::Now() - start_time_tick_);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request()->net_log().AddEvent(
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          is_fallback_ ?
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              net::NetLog::TYPE_APPCACHE_DELIVERING_FALLBACK_RESPONSE :
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              net::NetLog::TYPE_APPCACHE_DELIVERING_CACHED_RESPONSE);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      storage_->LoadResponseInfo(
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          manifest_url_, group_id_, entry_.response_id(), this);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AppCacheURLRequestJob::BeginExecutableHandlerDelivery() {
1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(CommandLine::ForCurrentProcess()->
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            HasSwitch(kEnableExecutableHandlers));
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!storage_->service()->handler_factory()) {
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    BeginErrorDelivery("missing handler factory");
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  request()->net_log().AddEvent(
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      net::NetLog::TYPE_APPCACHE_DELIVERING_EXECUTABLE_RESPONSE);
1447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // We defer job delivery until the executable handler is spun up and
1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // provides a response. The sequence goes like this...
1477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  //
1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // 1. First we load the cache.
1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // 2. Then if the handler is not spun up, we load the script resource which
1507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  //    is needed to spin it up.
1517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // 3. Then we ask then we ask the handler to compute a response.
1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // 4. Finally we deilver that response to the caller.
1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  storage_->LoadCache(cache_id_, this);
1547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AppCacheURLRequestJob::OnCacheLoaded(AppCache* cache, int64 cache_id) {
1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK_EQ(cache_id_, cache_id);
1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(!has_been_killed());
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!cache) {
1617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    BeginErrorDelivery("cache load failed");
1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Keep references to ensure they don't go out of scope until job completion.
1667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  cache_ = cache;
1677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  group_ = cache->owning_group();
1687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // If the handler is spun up, ask it to compute a response.
1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AppCacheExecutableHandler* handler =
1717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      cache->GetExecutableHandler(entry_.response_id());
1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (handler) {
1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    InvokeExecutableHandler(handler);
1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Handler is not spun up yet, load the script resource to do that.
1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // NOTE: This is not ideal since multiple jobs may be doing this,
1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // concurrently but close enough for now, the first to load the script
1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // will win.
1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Read the script data, truncating if its too large.
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // NOTE: we just issue one read and don't bother chaining if the resource
1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // is very (very) large, close enough for now.
1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const int64 kLimit = 500 * 1000;
1867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_buffer_ = new net::GrowableIOBuffer();
1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_buffer_->SetCapacity(kLimit);
1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_reader_.reset(storage_->CreateResponseReader(
1897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      manifest_url_, group_id_, entry_.response_id()));
1907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_reader_->ReadData(
191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      handler_source_buffer_.get(),
192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kLimit,
1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&AppCacheURLRequestJob::OnExecutableSourceLoaded,
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 base::Unretained(this)));
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AppCacheURLRequestJob::OnExecutableSourceLoaded(int result) {
1987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(!has_been_killed());
1997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_reader_.reset();
2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (result < 0) {
2017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    BeginErrorDelivery("script source load failed");
2027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_buffer_->SetCapacity(result);  // Free up some memory.
2067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AppCacheExecutableHandler* handler = cache_->GetOrCreateExecutableHandler(
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      entry_.response_id(), handler_source_buffer_.get());
2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_buffer_ = NULL;  // not needed anymore
2107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (handler) {
2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    InvokeExecutableHandler(handler);
2127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BeginErrorDelivery("factory failed to produce a handler");
2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AppCacheURLRequestJob::InvokeExecutableHandler(
2197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    AppCacheExecutableHandler* handler) {
2207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler->HandleRequest(
2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      request(),
2227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&AppCacheURLRequestJob::OnExecutableResponseCallback,
2237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                 weak_factory_.GetWeakPtr()));
2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AppCacheURLRequestJob::OnExecutableResponseCallback(
2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const AppCacheExecutableHandler::Response& response) {
2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(!has_been_killed());
2297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (response.use_network) {
2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    delivery_type_ = NETWORK_DELIVERY;
2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    storage_ = NULL;
2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    BeginDelivery();
2337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
2347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!response.cached_resource_url.is_empty()) {
2377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    AppCacheEntry* entry_ptr = cache_->GetEntry(response.cached_resource_url);
2387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (entry_ptr && !entry_ptr->IsExecutable()) {
2397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      entry_ = *entry_ptr;
2407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      BeginDelivery();
2417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!response.redirect_url.is_empty()) {
2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // TODO(michaeln): playback a redirect
2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // response_headers_(new HttpResponseHeaders(response_headers)),
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // fallthru for now to deliver an error
2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Otherwise, return an error.
2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BeginErrorDelivery("handler returned an invalid response");
2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AppCacheURLRequestJob::BeginErrorDelivery(const char* message) {
2567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (host_)
2577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    host_->frontend()->OnLogMessage(host_->host_id(), LOG_ERROR, message);
2587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  delivery_type_ = ERROR_DELIVERY;
2597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  storage_ = NULL;
2607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BeginDelivery();
2617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppCacheURLRequestJob::~AppCacheURLRequestJob() {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (storage_)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    storage_->CancelDelegateCallbacks(this);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::OnResponseInfoLoaded(
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheResponseInfo* response_info, int64 response_id) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_delivering_appcache_response());
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<AppCacheURLRequestJob> protect(this);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_info) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info_ = response_info;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reader_.reset(storage_->CreateResponseReader(
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_, group_id_, entry_.response_id()));
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_range_request())
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetupRangeResponse();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyHeadersComplete();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A resource that is expected to be in the appcache is missing.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See http://code.google.com/p/chromium/issues/detail?id=50657
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Instead of failing the request, we restart the request. The retry
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // attempt will fallthru to the network instead of trying to load
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // from the appcache.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               entry_.response_id());
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache_entry_not_found_ = true;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyRestartRequired();
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const net::HttpResponseInfo* AppCacheURLRequestJob::http_info() const {
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!info_.get())
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
297b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (range_response_info_)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return range_response_info_.get();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return info_->http_response_info();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::SetupRangeResponse() {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_range_request() && info_.get() && reader_.get() &&
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         is_delivering_appcache_response());
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int resource_size = static_cast<int>(info_->response_data_size());
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (resource_size < 0 || !range_requested_.ComputeBounds(resource_size)) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range_requested_ = net::HttpByteRange();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(range_requested_.HasFirstBytePosition() &&
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         range_requested_.HasLastBytePosition());
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int offset = static_cast<int>(range_requested_.first_byte_position());
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int length = static_cast<int>(range_requested_.last_byte_position() -
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                range_requested_.first_byte_position() + 1);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell the reader about the range to read.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reader_->SetReadRange(offset, length);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make a copy of the full response headers and fix them up
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for the range we'll be returning.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kLengthHeader[] = "Content-Length";
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kRangeHeader[] = "Content-Range";
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kPartialStatusLine[] = "HTTP/1.1 206 Partial Content";
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  range_response_info_.reset(
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new net::HttpResponseInfo(*info_->http_response_info()));
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  net::HttpResponseHeaders* headers = range_response_info_->headers.get();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers->RemoveHeader(kLengthHeader);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers->RemoveHeader(kRangeHeader);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers->ReplaceStatusLine(kPartialStatusLine);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers->AddHeader(
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringPrintf("%s: %d", kLengthHeader, length));
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers->AddHeader(
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringPrintf("%s: bytes %d-%d/%d",
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kRangeHeader,
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         offset,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         offset + length - 1,
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         resource_size));
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::OnReadComplete(int result) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_delivering_appcache_response());
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == 0) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyDone(net::URLRequestStatus());
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (result < 0) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               entry_.response_id());
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result));
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetStatus(net::URLRequestStatus());  // Clear the IO_PENDING status
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyReadComplete(result);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// net::URLRequestJob overrides ------------------------------------------------
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::Start() {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!has_been_started());
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_been_started_ = true;
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  start_time_tick_ = base::TimeTicks::Now();
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MaybeBeginDelivery();
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::Kill() {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_been_killed_) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_been_killed_ = true;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reader_.reset();
3687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    handler_source_reader_.reset();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (storage_) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      storage_->CancelDelegateCallbacks(this);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      storage_ = NULL;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    host_ = NULL;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequestJob::Kill();
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    weak_factory_.InvalidateWeakPtrs();
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::LoadState AppCacheURLRequestJob::GetLoadState() const {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_been_started())
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::LOAD_STATE_IDLE;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_delivery_orders())
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::LOAD_STATE_WAITING_FOR_APPCACHE;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delivery_type_ != APPCACHED_DELIVERY)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::LOAD_STATE_IDLE;
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!info_.get())
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::LOAD_STATE_WAITING_FOR_APPCACHE;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reader_.get() && reader_->IsReadPending())
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::LOAD_STATE_READING_RESPONSE;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net::LOAD_STATE_IDLE;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AppCacheURLRequestJob::GetMimeType(std::string* mime_type) const {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!http_info())
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return http_info()->headers->GetMimeType(mime_type);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AppCacheURLRequestJob::GetCharset(std::string* charset) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!http_info())
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return http_info()->headers->GetCharset(charset);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!http_info())
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *info = *http_info();
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int AppCacheURLRequestJob::GetResponseCode() const {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!http_info())
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return http_info()->headers->response_code();
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AppCacheURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size,
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        int *bytes_read) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_delivering_appcache_response());
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(buf_size, 0);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bytes_read);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!reader_->IsReadPending());
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reader_->ReadData(
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buf, buf_size, base::Bind(&AppCacheURLRequestJob::OnReadComplete,
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                base::Unretained(this)));
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::SetExtraRequestHeaders(
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::HttpRequestHeaders& headers) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<net::HttpByteRange> ranges;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &value) ||
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !net::HttpUtil::ParseRangeHeader(value, &ranges)) {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If multiple ranges are requested, we play dumb and
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // return the entire response with 200 OK.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ranges.size() == 1U)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range_requested_ = ranges[0];
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace appcache
446