Dismiss autofill popup on screen orientation change.
[chromium-blink-merge.git] / webkit / browser / appcache / appcache_disk_cache.cc
blobe486f1d7d6f18d1ae30082bc13188dd586e0bfb0
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "webkit/browser/appcache/appcache_disk_cache.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "net/base/cache_type.h"
14 #include "net/base/net_errors.h"
16 namespace appcache {
18 // A callback shim that provides storage for the 'backend_ptr' value
19 // and will delete a resulting ptr if completion occurs after its
20 // been canceled.
21 class AppCacheDiskCache::CreateBackendCallbackShim
22 : public base::RefCounted<CreateBackendCallbackShim> {
23 public:
24 explicit CreateBackendCallbackShim(AppCacheDiskCache* object)
25 : appcache_diskcache_(object) {
28 void Cancel() {
29 appcache_diskcache_ = NULL;
32 void Callback(int rv) {
33 if (appcache_diskcache_)
34 appcache_diskcache_->OnCreateBackendComplete(rv);
37 scoped_ptr<disk_cache::Backend> backend_ptr_; // Accessed directly.
39 private:
40 friend class base::RefCounted<CreateBackendCallbackShim>;
42 ~CreateBackendCallbackShim() {
45 AppCacheDiskCache* appcache_diskcache_; // Unowned pointer.
48 // An implementation of AppCacheDiskCacheInterface::Entry that's a thin
49 // wrapper around disk_cache::Entry.
50 class AppCacheDiskCache::EntryImpl : public Entry {
51 public:
52 explicit EntryImpl(disk_cache::Entry* disk_cache_entry)
53 : disk_cache_entry_(disk_cache_entry) {
54 DCHECK(disk_cache_entry);
57 // Entry implementation.
58 virtual int Read(int index, int64 offset, net::IOBuffer* buf, int buf_len,
59 const net::CompletionCallback& callback) OVERRIDE {
60 if (offset < 0 || offset > kint32max)
61 return net::ERR_INVALID_ARGUMENT;
62 return disk_cache_entry_->ReadData(
63 index, static_cast<int>(offset), buf, buf_len, callback);
66 virtual int Write(int index, int64 offset, net::IOBuffer* buf, int buf_len,
67 const net::CompletionCallback& callback) OVERRIDE {
68 if (offset < 0 || offset > kint32max)
69 return net::ERR_INVALID_ARGUMENT;
70 const bool kTruncate = true;
71 return disk_cache_entry_->WriteData(
72 index, static_cast<int>(offset), buf, buf_len, callback, kTruncate);
75 virtual int64 GetSize(int index) OVERRIDE {
76 return disk_cache_entry_->GetDataSize(index);
79 virtual void Close() OVERRIDE {
80 disk_cache_entry_->Close();
81 delete this;
84 private:
85 disk_cache::Entry* disk_cache_entry_;
88 // Separate object to hold state for each Create, Delete, or Doom call
89 // while the call is in-flight and to produce an EntryImpl upon completion.
90 class AppCacheDiskCache::ActiveCall {
91 public:
92 explicit ActiveCall(AppCacheDiskCache* owner)
93 : entry_(NULL),
94 owner_(owner),
95 entry_ptr_(NULL) {
98 int CreateEntry(int64 key, Entry** entry,
99 const net::CompletionCallback& callback) {
100 int rv = owner_->disk_cache()->CreateEntry(
101 base::Int64ToString(key), &entry_ptr_,
102 base::Bind(&ActiveCall::OnAsyncCompletion, base::Unretained(this)));
103 return HandleImmediateReturnValue(rv, entry, callback);
106 int OpenEntry(int64 key, Entry** entry,
107 const net::CompletionCallback& callback) {
108 int rv = owner_->disk_cache()->OpenEntry(
109 base::Int64ToString(key), &entry_ptr_,
110 base::Bind(&ActiveCall::OnAsyncCompletion, base::Unretained(this)));
111 return HandleImmediateReturnValue(rv, entry, callback);
114 int DoomEntry(int64 key, const net::CompletionCallback& callback) {
115 int rv = owner_->disk_cache()->DoomEntry(
116 base::Int64ToString(key),
117 base::Bind(&ActiveCall::OnAsyncCompletion, base::Unretained(this)));
118 return HandleImmediateReturnValue(rv, NULL, callback);
121 private:
122 int HandleImmediateReturnValue(int rv, Entry** entry,
123 const net::CompletionCallback& callback) {
124 if (rv == net::ERR_IO_PENDING) {
125 // OnAsyncCompletion will be called later.
126 callback_ = callback;
127 entry_ = entry;
128 owner_->AddActiveCall(this);
129 return net::ERR_IO_PENDING;
131 if (rv == net::OK && entry)
132 *entry = new EntryImpl(entry_ptr_);
133 delete this;
134 return rv;
137 void OnAsyncCompletion(int rv) {
138 owner_->RemoveActiveCall(this);
139 if (rv == net::OK && entry_)
140 *entry_ = new EntryImpl(entry_ptr_);
141 callback_.Run(rv);
142 callback_.Reset();
143 delete this;
146 Entry** entry_;
147 net::CompletionCallback callback_;
148 AppCacheDiskCache* owner_;
149 disk_cache::Entry* entry_ptr_;
152 AppCacheDiskCache::AppCacheDiskCache()
153 : is_disabled_(false) {
156 AppCacheDiskCache::~AppCacheDiskCache() {
157 if (create_backend_callback_.get()) {
158 create_backend_callback_->Cancel();
159 create_backend_callback_ = NULL;
160 OnCreateBackendComplete(net::ERR_ABORTED);
162 disk_cache_.reset();
163 STLDeleteElements(&active_calls_);
166 int AppCacheDiskCache::InitWithDiskBackend(
167 const base::FilePath& disk_cache_directory, int disk_cache_size, bool force,
168 base::MessageLoopProxy* cache_thread,
169 const net::CompletionCallback& callback) {
170 return Init(net::APP_CACHE, disk_cache_directory,
171 disk_cache_size, force, cache_thread, callback);
174 int AppCacheDiskCache::InitWithMemBackend(
175 int mem_cache_size, const net::CompletionCallback& callback) {
176 return Init(net::MEMORY_CACHE, base::FilePath(), mem_cache_size, false, NULL,
177 callback);
180 void AppCacheDiskCache::Disable() {
181 if (is_disabled_)
182 return;
184 is_disabled_ = true;
186 if (create_backend_callback_.get()) {
187 create_backend_callback_->Cancel();
188 create_backend_callback_ = NULL;
189 OnCreateBackendComplete(net::ERR_ABORTED);
193 int AppCacheDiskCache::CreateEntry(int64 key, Entry** entry,
194 const net::CompletionCallback& callback) {
195 DCHECK(entry);
196 DCHECK(!callback.is_null());
197 if (is_disabled_)
198 return net::ERR_ABORTED;
200 if (is_initializing()) {
201 pending_calls_.push_back(PendingCall(CREATE, key, entry, callback));
202 return net::ERR_IO_PENDING;
205 if (!disk_cache_)
206 return net::ERR_FAILED;
208 return (new ActiveCall(this))->CreateEntry(key, entry, callback);
211 int AppCacheDiskCache::OpenEntry(int64 key, Entry** entry,
212 const net::CompletionCallback& callback) {
213 DCHECK(entry);
214 DCHECK(!callback.is_null());
215 if (is_disabled_)
216 return net::ERR_ABORTED;
218 if (is_initializing()) {
219 pending_calls_.push_back(PendingCall(OPEN, key, entry, callback));
220 return net::ERR_IO_PENDING;
223 if (!disk_cache_)
224 return net::ERR_FAILED;
226 return (new ActiveCall(this))->OpenEntry(key, entry, callback);
229 int AppCacheDiskCache::DoomEntry(int64 key,
230 const net::CompletionCallback& callback) {
231 DCHECK(!callback.is_null());
232 if (is_disabled_)
233 return net::ERR_ABORTED;
235 if (is_initializing()) {
236 pending_calls_.push_back(PendingCall(DOOM, key, NULL, callback));
237 return net::ERR_IO_PENDING;
240 if (!disk_cache_)
241 return net::ERR_FAILED;
243 return (new ActiveCall(this))->DoomEntry(key, callback);
246 AppCacheDiskCache::PendingCall::PendingCall()
247 : call_type(CREATE),
248 key(0),
249 entry(NULL) {
252 AppCacheDiskCache::PendingCall::PendingCall(PendingCallType call_type,
253 int64 key,
254 Entry** entry,
255 const net::CompletionCallback& callback)
256 : call_type(call_type),
257 key(key),
258 entry(entry),
259 callback(callback) {
262 AppCacheDiskCache::PendingCall::~PendingCall() {}
264 int AppCacheDiskCache::Init(net::CacheType cache_type,
265 const base::FilePath& cache_directory,
266 int cache_size, bool force,
267 base::MessageLoopProxy* cache_thread,
268 const net::CompletionCallback& callback) {
269 DCHECK(!is_initializing() && !disk_cache_.get());
270 is_disabled_ = false;
271 create_backend_callback_ = new CreateBackendCallbackShim(this);
273 int rv = disk_cache::CreateCacheBackend(
274 cache_type, net::CACHE_BACKEND_DEFAULT, cache_directory, cache_size,
275 force, cache_thread, NULL, &(create_backend_callback_->backend_ptr_),
276 base::Bind(&CreateBackendCallbackShim::Callback,
277 create_backend_callback_));
278 if (rv == net::ERR_IO_PENDING)
279 init_callback_ = callback;
280 else
281 OnCreateBackendComplete(rv);
282 return rv;
285 void AppCacheDiskCache::OnCreateBackendComplete(int rv) {
286 if (rv == net::OK) {
287 disk_cache_ = create_backend_callback_->backend_ptr_.Pass();
289 create_backend_callback_ = NULL;
291 // Invoke our clients callback function.
292 if (!init_callback_.is_null()) {
293 init_callback_.Run(rv);
294 init_callback_.Reset();
297 // Service pending calls that were queued up while we were initializing.
298 for (PendingCalls::const_iterator iter = pending_calls_.begin();
299 iter < pending_calls_.end(); ++iter) {
300 int rv = net::ERR_FAILED;
301 switch (iter->call_type) {
302 case CREATE:
303 rv = CreateEntry(iter->key, iter->entry, iter->callback);
304 break;
305 case OPEN:
306 rv = OpenEntry(iter->key, iter->entry, iter->callback);
307 break;
308 case DOOM:
309 rv = DoomEntry(iter->key, iter->callback);
310 break;
311 default:
312 NOTREACHED();
313 break;
315 if (rv != net::ERR_IO_PENDING)
316 iter->callback.Run(rv);
318 pending_calls_.clear();
321 } // namespace appcache