summaryrefslogtreecommitdiffstats
path: root/webkit/appcache/appcache_response.h
blob: c791a01c42d75db12d7ad2a83b806b81f2428d95 (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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// Copyright (c) 2009 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 WEBKIT_APPCACHE_APPCACHE_RESPONSE_H_
#define WEBKIT_APPCACHE_APPCACHE_RESPONSE_H_

#include "base/logging.h"
#include "base/ref_counted.h"
#include "net/base/completion_callback.h"
#include "net/http/http_response_info.h"
#include "webkit/appcache/appcache_service.h"
#include "webkit/appcache/appcache_storage.h"

namespace net {
class IOBuffer;
}
namespace disk_cache {
class Backend;
};


namespace appcache {

// Response info for a particular response id. Instances are tracked in
// the working set.
class AppCacheResponseInfo
    : public base::RefCounted<AppCacheResponseInfo> {

  // AppCacheResponseInfo takes ownership of the http_info.
  AppCacheResponseInfo(AppCacheService* service, int64 response_id,
                       net::HttpResponseInfo* http_info)
      : response_id_(response_id), http_response_info_(http_info),
        service_(service) {
    DCHECK(http_info);
    DCHECK(response_id != kNoResponseId);
    service_->storage()->working_set()->AddResponseInfo(this);
  }

  ~AppCacheResponseInfo() {
    service_->storage()->working_set()->RemoveResponseInfo(this);
  }

  int64 response_id() const { return response_id_; }

  const net::HttpResponseInfo* http_response_info() const {
    return http_response_info_.get();
  }

 private:
  const int64 response_id_;
  const scoped_ptr<net::HttpResponseInfo> http_response_info_;
  const AppCacheService* service_;
};

// Common base class for response reader and writer.
class AppCacheResponseIO {
 public:
  virtual ~AppCacheResponseIO() {}
  int64 response_id() const { return response_id_; }
 protected:
  explicit AppCacheResponseIO(
      int64 response_id, disk_cache::Backend* disk_cache)
      : response_id_(response_id), disk_cache_(disk_cache) {}
  const int64 response_id_;
  disk_cache::Backend* disk_cache_;
};

// A refcounted wrapper for HttpResponseInfo so we can apply the
// refcounting semantics used with IOBuffer with these structures too.
struct HttpResponseInfoIOBuffer
    : public base::RefCountedThreadSafe<HttpResponseInfoIOBuffer> {
  scoped_ptr<net::HttpResponseInfo> http_info;
};

// Reads existing response data from storage. If the object is deleted
// and there is a read in progress, the implementation will return
// immediately but will take care of any side effect of cancelling the
// operation.  In other words, instances are safe to delete at will.
class AppCacheResponseReader : public AppCacheResponseIO {
 public:
  // Reads http info from storage. Returns the number of bytes read
  // or a net:: error code. Guaranteed to not perform partial reads of
  // the info data. ERR_IO_PENDING is returned if the
  // operation could not be completed synchronously, in which case the reader
  // acquires a reference to the provided 'info_buf' until completion at which
  // time the callback is invoked with either a negative error code or the
  // number of bytes written. The 'info_buf' argument should contain a NULL
  // http_info when ReadInfo is called. The 'callback' is a required parameter.
  // Should only be called where there is no Read operation in progress.
  int ReadInfo(HttpResponseInfoIOBuffer* info_buf,
               net::CompletionCallback* callback) {
    DCHECK(info_buf && !info_buf->http_info.get());
    return -2;
  }

  // Reads data from storage. Returns the number of bytes read
  // or a net:: error code. EOF is indicated with a return value of zero.
  // ERR_IO_PENDING is returned if the operation could not be completed
  // synchronously, in which case the reader acquires a reference to the
  // provided 'buf' until completion at which time the callback is invoked
  // with either a negative error code or the number of bytes read. The
  // 'callback' is a required parameter.
  // Should only be called where there is no Read operation in progress.
  int ReadData(net::IOBuffer* buf, int buf_len,
               net::CompletionCallback* callback) { return -2; }

  // Returns true if there is a read operation, for data or info, pending.
  bool IsReadPending() { return false; }

  // Used to support range requests. If not called, the reader will
  // read the entire response body. If called, this must be called prior
  // to the first call to the ReadData method.
  void SetReadRange(int64 offset, int64 length) {
    range_offset_ = offset;
    range_length_ = length;
  }

 private:
  friend class AppCacheStorageImpl;
  friend class MockAppCacheStorage;

  // Should only be constructed by the storage class.
  explicit AppCacheResponseReader(
      int64 response_id, disk_cache::Backend* disk_cache)
      : AppCacheResponseIO(response_id, disk_cache),
        range_offset_(0), range_length_(kint64max) {}

  int64 range_offset_;
  int64 range_length_;
};

// Writes new response data to storage. If the object is deleted
// and there is a write in progress, the implementation will return
// immediately but will take care of any side effect of cancelling the
// operation. In other words, instances are safe to delete at will.
class AppCacheResponseWriter : public AppCacheResponseIO {
 public:
  // Writes the http info to storage. Returns the number of bytes written
  // or a net:: error code. ERR_IO_PENDING is returned if the
  // operation could not be completed synchronously, in which case the writer
  // acquires a reference to the provided 'info_buf' until completion at which
  // time the callback is invoked with either a negative error code or the
  // number of bytes written. The 'callback' is a required parameter. The
  // contents of 'info_buf' are not modified.
  // Should only be called where there is no Write operation in progress.
  int WriteInfo(HttpResponseInfoIOBuffer* info_buf,
                net::CompletionCallback* callback) {
    DCHECK(info_buf && info_buf->http_info.get());
    return -2;
  }

  // Writes data to storage. Returns the number of bytes written
  // or a net:: error code. Guaranteed to not perform partial writes.
  // ERR_IO_PENDING is returned if the operation could not be completed
  // synchronously, in which case the writer acquires a reference to the
  // provided 'buf' until completion at which time the callback is invoked
  // with either a negative error code or the number of bytes written. The
  // 'callback' is a required parameter. The contents of 'buf' are not
  // modified.
  // Should only be called where there is no Write operation in progress.
  int WriteData(net::IOBuffer* buf, int buf_len,
                net::CompletionCallback* callback) { return -2; }

  // Returns true if there is a write pending.
  bool IsWritePending() { return false; }

 private:
  friend class AppCacheStorageImpl;
  friend class MockAppCacheStorage;

  // Should only be constructed by the storage class.
  explicit AppCacheResponseWriter(
      int64 response_id, disk_cache::Backend* disk_cache)
      : AppCacheResponseIO(response_id, disk_cache) {}
};

}  // namespace appcache

#endif  // WEBKIT_APPCACHE_APPCACHE_RESPONSE_H_