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)
5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/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"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache.h"
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_group.h"
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_histograms.h"
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_host.h"
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/appcache/appcache_service_impl.h"
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "net/base/io_buffer.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_headers.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_util.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace content {
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,
36effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    AppCacheHost* host,
37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    bool is_main_resource)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : net::URLRequestJob(request, network_delegate),
397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      host_(host),
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      storage_(storage),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_been_started_(false), has_been_killed_(false),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delivery_type_(AWAITING_DELIVERY_ORDERS),
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      group_id_(0), cache_id_(kAppCacheNoCacheId), is_fallback_(false),
44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      is_main_resource_(is_main_resource),
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cache_entry_not_found_(false),
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(storage_);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::DeliverAppCachedResponse(
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& manifest_url, int64 group_id, int64 cache_id,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AppCacheEntry& entry, bool is_fallback) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!has_delivery_orders());
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry.has_response_id());
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delivery_type_ = APPCACHED_DELIVERY;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest_url_ = manifest_url;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  group_id_ = group_id;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_id_ = cache_id;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry_ = entry;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_fallback_ = is_fallback;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MaybeBeginDelivery();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::DeliverNetworkResponse() {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!has_delivery_orders());
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delivery_type_ = NETWORK_DELIVERY;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  storage_ = NULL;  // not needed
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MaybeBeginDelivery();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::DeliverErrorResponse() {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!has_delivery_orders());
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delivery_type_ = ERROR_DELIVERY;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  storage_ = NULL;  // not needed
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MaybeBeginDelivery();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::MaybeBeginDelivery() {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_been_started() && has_delivery_orders()) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start asynchronously so that all error reporting and data
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // callbacks happen as they would for network requests.
82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AppCacheURLRequestJob::BeginDelivery,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_factory_.GetWeakPtr()));
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::BeginDelivery() {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(has_delivery_orders() && has_been_started());
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_been_killed())
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (delivery_type_) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NETWORK_DELIVERY:
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AppCacheHistograms::AddNetworkJobStartDelaySample(
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::TimeTicks::Now() - start_time_tick_);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // To fallthru to the network, we restart the request which will
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // cause a new job to be created to retrieve the resource from the
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // network. Our caller is responsible for arranging to not re-intercept
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the same request.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NotifyRestartRequired();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ERROR_DELIVERY:
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AppCacheHistograms::AddErrorJobStartDelaySample(
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::TimeTicks::Now() - start_time_tick_);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request()->net_log().AddEvent(
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_APPCACHE_DELIVERING_ERROR_RESPONSE);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             net::ERR_FAILED));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case APPCACHED_DELIVERY:
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (entry_.IsExecutable()) {
1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        BeginExecutableHandlerDelivery();
1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AppCacheHistograms::AddAppCacheJobStartDelaySample(
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::TimeTicks::Now() - start_time_tick_);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request()->net_log().AddEvent(
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          is_fallback_ ?
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              net::NetLog::TYPE_APPCACHE_DELIVERING_FALLBACK_RESPONSE :
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              net::NetLog::TYPE_APPCACHE_DELIVERING_CACHED_RESPONSE);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      storage_->LoadResponseInfo(
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          manifest_url_, group_id_, entry_.response_id(), this);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AppCacheURLRequestJob::BeginExecutableHandlerDelivery() {
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(CommandLine::ForCurrentProcess()->
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            HasSwitch(kEnableExecutableHandlers));
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!storage_->service()->handler_factory()) {
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    BeginErrorDelivery("missing handler factory");
1417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  request()->net_log().AddEvent(
1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      net::NetLog::TYPE_APPCACHE_DELIVERING_EXECUTABLE_RESPONSE);
1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // We defer job delivery until the executable handler is spun up and
1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // provides a response. The sequence goes like this...
1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  //
1507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // 1. First we load the cache.
1517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // 2. Then if the handler is not spun up, we load the script resource which
1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  //    is needed to spin it up.
1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // 3. Then we ask then we ask the handler to compute a response.
1547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // 4. Finally we deilver that response to the caller.
1557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  storage_->LoadCache(cache_id_, this);
1567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AppCacheURLRequestJob::OnCacheLoaded(AppCache* cache, int64 cache_id) {
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK_EQ(cache_id_, cache_id);
1607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(!has_been_killed());
1617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!cache) {
1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    BeginErrorDelivery("cache load failed");
1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
1657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Keep references to ensure they don't go out of scope until job completion.
1687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  cache_ = cache;
1697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  group_ = cache->owning_group();
1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // If the handler is spun up, ask it to compute a response.
1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AppCacheExecutableHandler* handler =
1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      cache->GetExecutableHandler(entry_.response_id());
1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (handler) {
1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    InvokeExecutableHandler(handler);
1767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Handler is not spun up yet, load the script resource to do that.
1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // NOTE: This is not ideal since multiple jobs may be doing this,
1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // concurrently but close enough for now, the first to load the script
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // will win.
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Read the script data, truncating if its too large.
1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // NOTE: we just issue one read and don't bother chaining if the resource
1867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // is very (very) large, close enough for now.
1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const int64 kLimit = 500 * 1000;
1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_buffer_ = new net::GrowableIOBuffer();
1897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_buffer_->SetCapacity(kLimit);
1907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_reader_.reset(storage_->CreateResponseReader(
1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      manifest_url_, group_id_, entry_.response_id()));
1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_reader_->ReadData(
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      handler_source_buffer_.get(),
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kLimit,
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&AppCacheURLRequestJob::OnExecutableSourceLoaded,
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 base::Unretained(this)));
1977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AppCacheURLRequestJob::OnExecutableSourceLoaded(int result) {
2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(!has_been_killed());
2017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_reader_.reset();
2027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (result < 0) {
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    BeginErrorDelivery("script source load failed");
2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
2057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_buffer_->SetCapacity(result);  // Free up some memory.
2087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AppCacheExecutableHandler* handler = cache_->GetOrCreateExecutableHandler(
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      entry_.response_id(), handler_source_buffer_.get());
2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler_source_buffer_ = NULL;  // not needed anymore
2127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (handler) {
2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    InvokeExecutableHandler(handler);
2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BeginErrorDelivery("factory failed to produce a handler");
2187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AppCacheURLRequestJob::InvokeExecutableHandler(
2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    AppCacheExecutableHandler* handler) {
2227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  handler->HandleRequest(
2237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      request(),
2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&AppCacheURLRequestJob::OnExecutableResponseCallback,
2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                 weak_factory_.GetWeakPtr()));
2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AppCacheURLRequestJob::OnExecutableResponseCallback(
2297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const AppCacheExecutableHandler::Response& response) {
2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(!has_been_killed());
2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (response.use_network) {
2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    delivery_type_ = NETWORK_DELIVERY;
2337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    storage_ = NULL;
2347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    BeginDelivery();
2357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
2367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!response.cached_resource_url.is_empty()) {
2397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    AppCacheEntry* entry_ptr = cache_->GetEntry(response.cached_resource_url);
2407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (entry_ptr && !entry_ptr->IsExecutable()) {
2417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      entry_ = *entry_ptr;
2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      BeginDelivery();
2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!response.redirect_url.is_empty()) {
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // TODO(michaeln): playback a redirect
2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // response_headers_(new HttpResponseHeaders(response_headers)),
2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // fallthru for now to deliver an error
2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Otherwise, return an error.
2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BeginErrorDelivery("handler returned an invalid response");
2557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AppCacheURLRequestJob::BeginErrorDelivery(const char* message) {
2587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (host_)
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    host_->frontend()->OnLogMessage(host_->host_id(), APPCACHE_LOG_ERROR,
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                    message);
2617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  delivery_type_ = ERROR_DELIVERY;
2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  storage_ = NULL;
2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BeginDelivery();
2647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppCacheURLRequestJob::~AppCacheURLRequestJob() {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (storage_)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    storage_->CancelDelegateCallbacks(this);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::OnResponseInfoLoaded(
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheResponseInfo* response_info, int64 response_id) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_delivering_appcache_response());
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<AppCacheURLRequestJob> protect(this);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_info) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info_ = response_info;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reader_.reset(storage_->CreateResponseReader(
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        manifest_url_, group_id_, entry_.response_id()));
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_range_request())
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetupRangeResponse();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyHeadersComplete();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (storage_->service()->storage() == storage_) {
2861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // A resource that is expected to be in the appcache is missing.
2871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // See http://code.google.com/p/chromium/issues/detail?id=50657
2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Instead of failing the request, we restart the request. The retry
2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // attempt will fallthru to the network instead of trying to load
2901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // from the appcache.
2911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_,
2921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                 entry_.response_id());
293effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      AppCacheHistograms::CountResponseRetrieval(
294effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          false, is_main_resource_, manifest_url_.GetOrigin());
2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache_entry_not_found_ = true;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyRestartRequired();
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const net::HttpResponseInfo* AppCacheURLRequestJob::http_info() const {
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!info_.get())
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
304b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (range_response_info_)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return range_response_info_.get();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return info_->http_response_info();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::SetupRangeResponse() {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_range_request() && info_.get() && reader_.get() &&
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         is_delivering_appcache_response());
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int resource_size = static_cast<int>(info_->response_data_size());
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (resource_size < 0 || !range_requested_.ComputeBounds(resource_size)) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range_requested_ = net::HttpByteRange();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(range_requested_.IsValid());
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int offset = static_cast<int>(range_requested_.first_byte_position());
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int length = static_cast<int>(range_requested_.last_byte_position() -
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                range_requested_.first_byte_position() + 1);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell the reader about the range to read.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reader_->SetReadRange(offset, length);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make a copy of the full response headers and fix them up
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for the range we'll be returning.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  range_response_info_.reset(
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new net::HttpResponseInfo(*info_->http_response_info()));
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  net::HttpResponseHeaders* headers = range_response_info_->headers.get();
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  headers->UpdateWithNewRange(
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      range_requested_, resource_size, true /* replace status line */);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::OnReadComplete(int result) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_delivering_appcache_response());
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == 0) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyDone(net::URLRequestStatus());
339effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    AppCacheHistograms::CountResponseRetrieval(
340effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        true, is_main_resource_, manifest_url_.GetOrigin());
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (result < 0) {
3421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (storage_->service()->storage() == storage_) {
3431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_,
3441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                 entry_.response_id());
3451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result));
347effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    AppCacheHistograms::CountResponseRetrieval(
348effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        false, is_main_resource_, manifest_url_.GetOrigin());
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;
3741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    info_ = NULL;
3751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    cache_ = NULL;
3761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    group_ = NULL;
3771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    range_response_info_.reset();
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequestJob::Kill();
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    weak_factory_.InvalidateWeakPtrs();
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::LoadState AppCacheURLRequestJob::GetLoadState() const {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_been_started())
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::LOAD_STATE_IDLE;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_delivery_orders())
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::LOAD_STATE_WAITING_FOR_APPCACHE;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delivery_type_ != APPCACHED_DELIVERY)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::LOAD_STATE_IDLE;
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!info_.get())
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::LOAD_STATE_WAITING_FOR_APPCACHE;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reader_.get() && reader_->IsReadPending())
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::LOAD_STATE_READING_RESPONSE;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net::LOAD_STATE_IDLE;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AppCacheURLRequestJob::GetMimeType(std::string* mime_type) const {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!http_info())
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return http_info()->headers->GetMimeType(mime_type);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AppCacheURLRequestJob::GetCharset(std::string* charset) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!http_info())
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return http_info()->headers->GetCharset(charset);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!http_info())
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *info = *http_info();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int AppCacheURLRequestJob::GetResponseCode() const {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!http_info())
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return http_info()->headers->response_code();
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AppCacheURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size,
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        int *bytes_read) {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_delivering_appcache_response());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(buf_size, 0);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bytes_read);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!reader_->IsReadPending());
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reader_->ReadData(
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buf, buf_size, base::Bind(&AppCacheURLRequestJob::OnReadComplete,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                base::Unretained(this)));
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppCacheURLRequestJob::SetExtraRequestHeaders(
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::HttpRequestHeaders& headers) {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<net::HttpByteRange> ranges;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &value) ||
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !net::HttpUtil::ParseRangeHeader(value, &ranges)) {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If multiple ranges are requested, we play dumb and
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // return the entire response with 200 OK.
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ranges.size() == 1U)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    range_requested_ = ranges[0];
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
449116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace content
450