summaryrefslogtreecommitdiffstats
path: root/net/http/partial_data.h
blob: 442bbb710e18e1456d93473d53fcea9951a8078e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright (c) 2011 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.

#ifndef NET_HTTP_PARTIAL_DATA_H_
#define NET_HTTP_PARTIAL_DATA_H_
#pragma once

#include "base/basictypes.h"
#include "net/base/completion_callback.h"
#include "net/http/http_byte_range.h"
#include "net/http/http_request_headers.h"

namespace disk_cache {
class Entry;
}

namespace net {

class HttpResponseHeaders;
class IOBuffer;

// This class provides support for dealing with range requests and the
// subsequent partial-content responses. We use sparse cache entries to store
// these requests. This class is tightly integrated with HttpCache::Transaction
// and it is intended to allow a cleaner implementation of that class.
//
// In order to fulfill range requests, we may have to perform a sequence of
// reads from the cache, interleaved with reads from the network / writes to the
// cache. This class basically keeps track of the data required to perform each
// of those individual network / cache requests.
class PartialData {
 public:
  PartialData();
  ~PartialData();

  // Performs initialization of the object by examining the request |headers|
  // and verifying that we can process the requested range. Returns true if
  // we can process the requested range, and false otherwise.
  bool Init(const HttpRequestHeaders& headers);

  // Sets the headers that we should use to make byte range requests. This is a
  // subset of the request extra headers, with byte-range related headers
  // removed.
  void SetHeaders(const HttpRequestHeaders& headers);

  // Restores the byte-range headers, by appending the byte range to the headers
  // provided to SetHeaders().
  void RestoreHeaders(HttpRequestHeaders* headers) const;

  // Starts the checks to perform a cache validation. Returns 0 when there is no
  // need to perform more operations because we reached the end of the request
  // (so 0 bytes should be actually returned to the user), a positive number to
  // indicate that PrepareCacheValidation should be called, or an appropriate
  // error code. If this method returns ERR_IO_PENDING, the |callback| will be
  // notified when the result is ready.
  int ShouldValidateCache(disk_cache::Entry* entry,
                          const CompletionCallback& callback);

  // Builds the required |headers| to perform the proper cache validation for
  // the next range to be fetched.
  void PrepareCacheValidation(disk_cache::Entry* entry,
                              HttpRequestHeaders* headers);

  // Returns true if the current range is stored in the cache.
  bool IsCurrentRangeCached() const;

  // Returns true if the current range is the last one needed to fulfill the
  // user's request.
  bool IsLastRange() const;

  // Extracts info from headers already stored in the cache. Returns false if
  // there is any problem with the headers. |truncated| should be true if we
  // have an incomplete 200 entry.
  bool UpdateFromStoredHeaders(const HttpResponseHeaders* headers,
                               disk_cache::Entry* entry, bool truncated);

  // Sets the byte current range to start again at zero (for a truncated entry).
  void SetRangeToStartDownload();

  // Returns true if the requested range is valid given the stored data.
  bool IsRequestedRangeOK();

  // Returns true if the response headers match what we expect, false otherwise.
  bool ResponseHeadersOK(const HttpResponseHeaders* headers);

  // Fixes the response headers to include the right content length and range.
  // |success| is the result of the whole request so if it's false, we'll change
  // the result code to be 416.
  void FixResponseHeaders(HttpResponseHeaders* headers, bool success);

  // Fixes the content length that we want to store in the cache.
  void FixContentLength(HttpResponseHeaders* headers);

  // Reads up to |data_len| bytes from the cache and stores them in the provided
  // buffer (|data|). Basically, this is just a wrapper around the API of the
  // cache that provides the right arguments for the current range. When the IO
  // operation completes, OnCacheReadCompleted() must be called with the result
  // of the operation.
  int CacheRead(disk_cache::Entry* entry, IOBuffer* data, int data_len,
                const net::CompletionCallback& callback);

  // Writes |data_len| bytes to cache. This is basically a wrapper around the
  // API of the cache that provides the right arguments for the current range.
  int CacheWrite(disk_cache::Entry* entry, IOBuffer* data, int data_len,
                 const net::CompletionCallback& callback);

  // This method should be called when CacheRead() finishes the read, to update
  // the internal state about the current range.
  void OnCacheReadCompleted(int result);

  // This method should be called after receiving data from the network, to
  // update the internal state about the current range.
  void OnNetworkReadCompleted(int result);

  bool initial_validation() const { return initial_validation_; }

 private:
  class Core;
  // Returns the length to use when scanning the cache.
  int GetNextRangeLen();

  // Completion routine for our callback.
  void GetAvailableRangeCompleted(int result, int64 start);

  int64 current_range_start_;
  int64 cached_start_;
  int64 resource_size_;
  int cached_min_len_;
  HttpByteRange byte_range_;  // The range requested by the user.
  // The clean set of extra headers (no ranges).
  HttpRequestHeaders extra_headers_;
  bool range_present_;  // True if next range entry is already stored.
  bool final_range_;
  bool sparse_entry_;
  bool truncated_;  // We have an incomplete 200 stored.
  bool initial_validation_;  // Only used for truncated entries.
  Core* core_;
  CompletionCallback callback_;

  DISALLOW_COPY_AND_ASSIGN(PartialData);
};

}  // namespace net

#endif  // NET_HTTP_PARTIAL_DATA_H_