13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef NET_HTTP_PARTIAL_DATA_H_
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define NET_HTTP_PARTIAL_DATA_H_
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h"
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/completion_callback.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_byte_range.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_request_headers.h"
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace disk_cache {
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass Entry;
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass HttpResponseHeaders;
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass IOBuffer;
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This class provides support for dealing with range requests and the
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// subsequent partial-content responses. We use sparse cache entries to store
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// these requests. This class is tightly integrated with HttpCache::Transaction
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and it is intended to allow a cleaner implementation of that class.
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// In order to fulfill range requests, we may have to perform a sequence of
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// reads from the cache, interleaved with reads from the network / writes to the
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// cache. This class basically keeps track of the data required to perform each
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// of those individual network / cache requests.
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass PartialData {
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  PartialData();
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~PartialData();
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Performs initialization of the object by examining the request |headers|
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // and verifying that we can process the requested range. Returns true if
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // we can process the requested range, and false otherwise.
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool Init(const HttpRequestHeaders& headers);
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Sets the headers that we should use to make byte range requests. This is a
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // subset of the request extra headers, with byte-range related headers
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // removed.
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void SetHeaders(const HttpRequestHeaders& headers);
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Restores the byte-range headers, by appending the byte range to the headers
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // provided to SetHeaders().
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void RestoreHeaders(HttpRequestHeaders* headers) const;
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Starts the checks to perform a cache validation. Returns 0 when there is no
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // need to perform more operations because we reached the end of the request
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (so 0 bytes should be actually returned to the user), a positive number to
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // indicate that PrepareCacheValidation should be called, or an appropriate
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // error code. If this method returns ERR_IO_PENDING, the |callback| will be
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // notified when the result is ready.
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int ShouldValidateCache(disk_cache::Entry* entry,
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          CompletionCallback* callback);
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Builds the required |headers| to perform the proper cache validation for
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the next range to be fetched.
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void PrepareCacheValidation(disk_cache::Entry* entry,
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              HttpRequestHeaders* headers);
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns true if the current range is stored in the cache.
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool IsCurrentRangeCached() const;
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns true if the current range is the last one needed to fulfill the
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // user's request.
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool IsLastRange() const;
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Extracts info from headers already stored in the cache. Returns false if
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // there is any problem with the headers. |truncated| should be true if we
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // have an incomplete 200 entry.
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool UpdateFromStoredHeaders(const HttpResponseHeaders* headers,
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                               disk_cache::Entry* entry, bool truncated);
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Sets the byte current range to start again at zero (for a truncated entry).
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void SetRangeToStartDownload();
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns true if the requested range is valid given the stored data.
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool IsRequestedRangeOK();
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns true if the response headers match what we expect, false otherwise.
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ResponseHeadersOK(const HttpResponseHeaders* headers);
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Fixes the response headers to include the right content length and range.
88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // |success| is the result of the whole request so if it's false, we'll change
89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // the result code to be 416.
90731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void FixResponseHeaders(HttpResponseHeaders* headers, bool success);
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Fixes the content length that we want to store in the cache.
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void FixContentLength(HttpResponseHeaders* headers);
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Reads up to |data_len| bytes from the cache and stores them in the provided
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // buffer (|data|). Basically, this is just a wrapper around the API of the
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // cache that provides the right arguments for the current range. When the IO
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // operation completes, OnCacheReadCompleted() must be called with the result
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // of the operation.
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int CacheRead(disk_cache::Entry* entry, IOBuffer* data, int data_len,
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                CompletionCallback* callback);
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Writes |data_len| bytes to cache. This is basically a wrapper around the
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // API of the cache that provides the right arguments for the current range.
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int CacheWrite(disk_cache::Entry* entry, IOBuffer* data, int data_len,
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                 CompletionCallback* callback);
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This method should be called when CacheRead() finishes the read, to update
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // the internal state about the current range.
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnCacheReadCompleted(int result);
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This method should be called after receiving data from the network, to
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // update the internal state about the current range.
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnNetworkReadCompleted(int result);
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool initial_validation() const { return initial_validation_; }
117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  class Core;
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns the length to use when scanning the cache.
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int GetNextRangeLen();
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Completion routine for our callback.
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void GetAvailableRangeCompleted(int result, int64 start);
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 current_range_start_;
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 cached_start_;
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 resource_size_;
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int cached_min_len_;
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  HttpByteRange byte_range_;  // The range requested by the user.
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The clean set of extra headers (no ranges).
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpRequestHeaders extra_headers_;
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool range_present_;  // True if next range entry is already stored.
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool final_range_;
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool sparse_entry_;
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool truncated_;  // We have an incomplete 200 stored.
137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool initial_validation_;  // Only used for truncated entries.
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Core* core_;
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CompletionCallback* callback_;
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(PartialData);
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // NET_HTTP_PARTIAL_DATA_H_
147