diff options
Diffstat (limited to 'webkit/appcache')
22 files changed, 745 insertions, 202 deletions
diff --git a/webkit/appcache/appcache.cc b/webkit/appcache/appcache.cc index 450f978..01bf37d 100644 --- a/webkit/appcache/appcache.cc +++ b/webkit/appcache/appcache.cc @@ -9,6 +9,7 @@ #include "webkit/appcache/appcache_host.h" #include "webkit/appcache/appcache_interfaces.h" #include "webkit/appcache/appcache_service.h" +#include "webkit/appcache/appcache_storage.h" namespace appcache { @@ -18,13 +19,13 @@ AppCache::AppCache(AppCacheService *service, int64 cache_id) online_whitelist_all_(false), is_complete_(false), service_(service) { - service_->AddCache(this); + service_->storage()->working_set()->AddCache(this); } AppCache::~AppCache() { DCHECK(associated_hosts_.empty()); DCHECK(!owning_group_); - service_->RemoveCache(this); + service_->storage()->working_set()->RemoveCache(this); } void AppCache::UnassociateHost(AppCacheHost* host) { diff --git a/webkit/appcache/appcache_group.cc b/webkit/appcache/appcache_group.cc index 67ca4cc..b45e90b 100644 --- a/webkit/appcache/appcache_group.cc +++ b/webkit/appcache/appcache_group.cc @@ -10,6 +10,7 @@ #include "webkit/appcache/appcache.h" #include "webkit/appcache/appcache_host.h" #include "webkit/appcache/appcache_service.h" +#include "webkit/appcache/appcache_storage.h" #include "webkit/appcache/appcache_update_job.h" namespace appcache { @@ -22,7 +23,7 @@ AppCacheGroup::AppCacheGroup(AppCacheService* service, newest_complete_cache_(NULL), update_job_(NULL), service_(service) { - service_->AddGroup(this); + service_->storage()->working_set()->AddGroup(this); } AppCacheGroup::~AppCacheGroup() { @@ -34,7 +35,7 @@ AppCacheGroup::~AppCacheGroup() { if (newest_complete_cache_) RemoveCache(newest_complete_cache_); - service_->RemoveGroup(this); + service_->storage()->working_set()->RemoveGroup(this); } void AppCacheGroup::AddObserver(Observer* observer) { diff --git a/webkit/appcache/appcache_group_unittest.cc b/webkit/appcache/appcache_group_unittest.cc index 6eeb209..e9b7acd 100644 --- a/webkit/appcache/appcache_group_unittest.cc +++ b/webkit/appcache/appcache_group_unittest.cc @@ -6,7 +6,7 @@ #include "webkit/appcache/appcache.h" #include "webkit/appcache/appcache_group.h" #include "webkit/appcache/appcache_host.h" -#include "webkit/appcache/appcache_service.h" +#include "webkit/appcache/mock_appcache_service.h" #include "webkit/appcache/appcache_update_job.h" namespace { @@ -46,7 +46,7 @@ class AppCacheGroupTest : public testing::Test { }; TEST(AppCacheGroupTest, AddRemoveCache) { - AppCacheService service; + MockAppCacheService service; scoped_refptr<AppCacheGroup> group = new AppCacheGroup(&service, GURL::EmptyGURL()); @@ -110,7 +110,7 @@ TEST(AppCacheGroupTest, AddRemoveCache) { } TEST(AppCacheGroupTest, CleanupUnusedGroup) { - AppCacheService service; + MockAppCacheService service; TestAppCacheFrontend frontend; AppCacheGroup* group = new AppCacheGroup(&service, GURL::EmptyGURL()); @@ -153,7 +153,7 @@ TEST(AppCacheGroupTest, CleanupUnusedGroup) { TEST(AppCacheGroupTest, StartUpdate) { /* TODO(jennb) - uncomment after AppCacheGroup::StartUpdate does something. - AppCacheService service; + MockAppCacheService service; scoped_refptr<AppCacheGroup> group = new AppCacheGroup(&service, GURL("http://foo.com")); diff --git a/webkit/appcache/appcache_host.cc b/webkit/appcache/appcache_host.cc index 77a0d96..50b24a5 100644 --- a/webkit/appcache/appcache_host.cc +++ b/webkit/appcache/appcache_host.cc @@ -25,7 +25,7 @@ AppCacheHost::~AppCacheHost() { FOR_EACH_OBSERVER(Observer, observers_, OnDestructionImminent(this)); if (associated_cache_.get()) associated_cache_->UnassociateHost(this); - service_->CancelLoads(this); + service_->storage()->CancelDelegateCallbacks(this); } void AppCacheHost::AddObserver(Observer* observer) { @@ -54,7 +54,7 @@ void AppCacheHost::SelectCache(const GURL& document_url, // results (or suggest changes to the algorihtms described in the spec // if the resulting behavior is just too insane). if (is_selection_pending()) { - service_->CancelLoads(this); + service_->storage()->CancelDelegateCallbacks(this); pending_selected_manifest_url_ = GURL::EmptyGURL(); pending_selected_cache_id_ = kNoCacheId; } else if (associated_cache()) { @@ -89,9 +89,11 @@ void AppCacheHost::SelectCache(const GURL& document_url, FinishCacheSelection(NULL, NULL); } +// TODO(michaeln): change method name to MarkEntryAsForeign for consistency void AppCacheHost::MarkAsForeignEntry(const GURL& document_url, int64 cache_document_was_loaded_from) { - service_->MarkAsForeignEntry(document_url, cache_document_was_loaded_from); + service_->storage()->MarkEntryAsForeign( + document_url, cache_document_was_loaded_from); SelectCache(document_url, kNoCacheId, GURL::EmptyGURL()); } @@ -191,11 +193,11 @@ Status AppCacheHost::GetStatus() { void AppCacheHost::LoadOrCreateGroup(const GURL& manifest_url) { DCHECK(manifest_url.is_valid()); pending_selected_manifest_url_ = manifest_url; - service_->LoadOrCreateGroup(manifest_url, this); + service_->storage()->LoadOrCreateGroup(manifest_url, this); } -void AppCacheHost::GroupLoadedCallback( - AppCacheGroup* group, const GURL& manifest_url) { +void AppCacheHost::OnGroupLoaded(AppCacheGroup* group, + const GURL& manifest_url) { DCHECK(manifest_url == pending_selected_manifest_url_); pending_selected_manifest_url_ = GURL::EmptyGURL(); FinishCacheSelection(NULL, group); @@ -204,10 +206,10 @@ void AppCacheHost::GroupLoadedCallback( void AppCacheHost::LoadCache(int64 cache_id) { DCHECK(cache_id != kNoCacheId); pending_selected_cache_id_ = cache_id; - service_->LoadCache(cache_id, this); + service_->storage()->LoadCache(cache_id, this); } -void AppCacheHost::CacheLoadedCallback(AppCache* cache, int64 cache_id) { +void AppCacheHost::OnCacheLoaded(AppCache* cache, int64 cache_id) { DCHECK(cache_id == pending_selected_cache_id_); pending_selected_cache_id_ = kNoCacheId; if (cache) diff --git a/webkit/appcache/appcache_host.h b/webkit/appcache/appcache_host.h index 9b7db30..5be3c5c 100644 --- a/webkit/appcache/appcache_host.h +++ b/webkit/appcache/appcache_host.h @@ -8,12 +8,12 @@ #include "base/observer_list.h" #include "base/ref_counted.h" #include "base/task.h" -#include "base/weak_ptr.h" #include "googleurl/src/gurl.h" #include "testing/gtest/include/gtest/gtest_prod.h" #include "webkit/appcache/appcache.h" #include "webkit/appcache/appcache_interfaces.h" #include "webkit/appcache/appcache_service.h" +#include "webkit/appcache/appcache_storage.h" class URLRequest; @@ -29,8 +29,7 @@ typedef Callback2<bool, void*>::Type StartUpdateCallback; typedef Callback2<bool, void*>::Type SwapCacheCallback; // Server-side representation of an application cache host. -class AppCacheHost : public base::SupportsWeakPtr<AppCacheHost>, - public AppCacheService::LoadClient { +class AppCacheHost : public AppCacheStorage::Delegate { public: class Observer { @@ -91,10 +90,10 @@ class AppCacheHost : public base::SupportsWeakPtr<AppCacheHost>, void LoadCache(int64 cache_id); void LoadOrCreateGroup(const GURL& manifest_url); - // LoadClient impl - virtual void CacheLoadedCallback(AppCache* cache, int64 cache_id); - virtual void GroupLoadedCallback(AppCacheGroup* group, - const GURL& manifest_url); + // AppCacheStorage::Delegate impl + virtual void OnCacheLoaded(AppCache* cache, int64 cache_id); + virtual void OnGroupLoaded(AppCacheGroup* group, + const GURL& manifest_url); void FinishCacheSelection(AppCache* cache, AppCacheGroup* group); void DoPendingGetStatus(); diff --git a/webkit/appcache/appcache_host_unittest.cc b/webkit/appcache/appcache_host_unittest.cc index cd1497b..cdfaee2 100644 --- a/webkit/appcache/appcache_host_unittest.cc +++ b/webkit/appcache/appcache_host_unittest.cc @@ -7,7 +7,7 @@ #include "webkit/appcache/appcache.h" #include "webkit/appcache/appcache_group.h" #include "webkit/appcache/appcache_host.h" -#include "webkit/appcache/appcache_service.h" +#include "webkit/appcache/mock_appcache_service.h" namespace appcache { @@ -65,7 +65,7 @@ class AppCacheHostTest : public testing::Test { } // Mock classes for the 'host' to work with - AppCacheService service_; // TODO(michaeln): make service mockable? + MockAppCacheService service_; MockFrontend mock_frontend_; // Mock callbacks we expect to receive from the 'host' @@ -179,7 +179,7 @@ TEST_F(AppCacheHostTest, FailedCacheLoad) { EXPECT_EQ(reinterpret_cast<void*>(-1), last_callback_param_); // Satisfy the load with NULL, a failure. - host.CacheLoadedCallback(NULL, kMockCacheId); + host.OnCacheLoaded(NULL, kMockCacheId); // Cache selection should have finished EXPECT_FALSE(host.is_selection_pending()); @@ -211,7 +211,7 @@ TEST_F(AppCacheHostTest, FailedGroupLoad) { EXPECT_EQ(reinterpret_cast<void*>(-1), last_callback_param_); // Satisfy the load will NULL, a failure. - host.GroupLoadedCallback(NULL, kMockManifestUrl); + host.OnGroupLoaded(NULL, kMockManifestUrl); // Cache selection should have finished EXPECT_FALSE(host.is_selection_pending()); diff --git a/webkit/appcache/appcache_interfaces.h b/webkit/appcache/appcache_interfaces.h index fcba1d8..223e560 100644 --- a/webkit/appcache/appcache_interfaces.h +++ b/webkit/appcache/appcache_interfaces.h @@ -20,6 +20,7 @@ extern const char kManifestMimeType[]; static const int kNoHostId = 0; static const int64 kNoCacheId = 0; +static const int64 kNoResponseId = 0; static const int64 kUnknownCacheId = -1; enum Status { diff --git a/webkit/appcache/appcache_response.h b/webkit/appcache/appcache_response.h new file mode 100644 index 0000000..c791a01 --- /dev/null +++ b/webkit/appcache/appcache_response.h @@ -0,0 +1,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_ + diff --git a/webkit/appcache/appcache_service.cc b/webkit/appcache/appcache_service.cc index c36ad1e..f0c8784 100644 --- a/webkit/appcache/appcache_service.cc +++ b/webkit/appcache/appcache_service.cc @@ -5,30 +5,24 @@ #include "webkit/appcache/appcache_service.h" #include "base/logging.h" -#include "base/ref_counted.h" -#include "webkit/appcache/appcache.h" #include "webkit/appcache/appcache_backend_impl.h" -#include "webkit/appcache/appcache_entry.h" -#include "webkit/appcache/appcache_group.h" +#include "webkit/appcache/appcache_storage_impl.h" namespace appcache { AppCacheService::AppCacheService() - : last_cache_id_(0), last_group_id_(0), - last_entry_id_(0), last_response_id_(0), - request_context_(NULL) { + : request_context_(NULL) { } AppCacheService::~AppCacheService() { DCHECK(backends_.empty()); - DCHECK(caches_.empty()); - DCHECK(groups_.empty()); } void AppCacheService::Initialize(const FilePath& cache_directory) { - // An empty cache directory indicates chrome incognito. - cache_directory_ = cache_directory; - // TODO(michaeln): load last_<foo>_ids from storage + DCHECK(!storage_.get()); + AppCacheStorageImpl* storage = new AppCacheStorageImpl(this); + storage->Initialize(cache_directory); + storage_.reset(storage); } void AppCacheService::RegisterBackend( @@ -43,61 +37,4 @@ void AppCacheService::UnregisterBackend( backends_.erase(backend_impl->process_id()); } -void AppCacheService::AddCache(AppCache* cache) { - int64 cache_id = cache->cache_id(); - DCHECK(caches_.find(cache_id) == caches_.end()); - caches_.insert(CacheMap::value_type(cache_id, cache)); -} - -void AppCacheService::RemoveCache(AppCache* cache) { - caches_.erase(cache->cache_id()); -} - -void AppCacheService::AddGroup(AppCacheGroup* group) { - const GURL& url = group->manifest_url(); - DCHECK(groups_.find(url) == groups_.end()); - groups_.insert(GroupMap::value_type(url, group)); -} - -void AppCacheService::RemoveGroup(AppCacheGroup* group) { - groups_.erase(group->manifest_url()); - - // TODO(jennb): if group is obsolete, delete from storage. -} - -void AppCacheService::LoadCache(int64 id, LoadClient* client) { - // TODO(michaeln): actually retrieve from storage if needed - client->CacheLoadedCallback(GetCache(id), id); -} - -void AppCacheService::LoadOrCreateGroup(const GURL& manifest_url, - LoadClient* client) { - // TODO(michaeln): actually retrieve from storage - scoped_refptr<AppCacheGroup> group = GetGroup(manifest_url); - if (!group.get()) { - group = new AppCacheGroup(this, manifest_url); - DCHECK(GetGroup(manifest_url)); - } - client->GroupLoadedCallback(group.get(), manifest_url); -} - -void AppCacheService::CancelLoads(LoadClient* client) { - // TODO(michaeln): remove client from loading lists -} - -void AppCacheService::MarkAsForeignEntry(const GURL& entry_url, - int64 cache_id) { - // Update the in-memory cache. - AppCache* cache = GetCache(cache_id); - if (cache) { - AppCacheEntry* entry = cache->GetEntry(entry_url); - DCHECK(entry); - if (entry) - entry->add_types(AppCacheEntry::FOREIGN); - } - - // TODO(michaeln): actually update in storage, and if this cache is - // being loaded be sure to update the memory cache upon load completion. -} - } // namespace appcache diff --git a/webkit/appcache/appcache_service.h b/webkit/appcache/appcache_service.h index 4dff28e..5cdaed4 100644 --- a/webkit/appcache/appcache_service.h +++ b/webkit/appcache/appcache_service.h @@ -5,40 +5,23 @@ #ifndef WEBKIT_APPCACHE_APPCACHE_SERVICE_H_ #define WEBKIT_APPCACHE_APPCACHE_SERVICE_H_ -#include <map> -#include <set> -#include <vector> - -#include "base/hash_tables.h" #include "base/file_path.h" -#include "base/ref_counted.h" -#include "base/task.h" -#include "googleurl/src/gurl.h" +#include "base/logging.h" +#include "base/scoped_ptr.h" +#include "testing/gtest/include/gtest/gtest_prod.h" +#include "webkit/appcache/appcache_storage.h" class URLRequestContext; namespace appcache { -class AppCache; class AppCacheBackendImpl; -class AppCacheGroup; // Class that manages the application cache service. Sends notifications // to many frontends. One instance per user-profile. Each instance has // exclusive access to it's cache_directory on disk. class AppCacheService { public: - - class LoadClient { - public: - virtual ~LoadClient() {} - - // If a load fails the object pointer will be NULL. - virtual void CacheLoadedCallback(AppCache* cache, int64 cache_id) = 0; - virtual void GroupLoadedCallback(AppCacheGroup* group, - const GURL& manifest_url) = 0; - }; - AppCacheService(); virtual ~AppCacheService(); @@ -56,71 +39,27 @@ class AppCacheService { // Track which processes are using this appcache service. void RegisterBackend(AppCacheBackendImpl* backend_impl); void UnregisterBackend(AppCacheBackendImpl* backend_impl); - AppCacheBackendImpl* GetBackend(int id) { - BackendMap::iterator it = backends_.find(id); + AppCacheBackendImpl* GetBackend(int id) const { + BackendMap::const_iterator it = backends_.find(id); return (it != backends_.end()) ? it->second : NULL; } - // Track what we have in our in-memory cache. - void AddCache(AppCache* cache); - void RemoveCache(AppCache* cache); - void AddGroup(AppCacheGroup* group); - void RemoveGroup(AppCacheGroup* group); - AppCache* GetCache(int64 id) { - CacheMap::iterator it = caches_.find(id); - return (it != caches_.end()) ? it->second : NULL; - } - AppCacheGroup* GetGroup(const GURL& manifest_url) { - GroupMap::iterator it = groups_.find(manifest_url); - return (it != groups_.end()) ? it->second : NULL; - } + AppCacheStorage* storage() const { return storage_.get(); } - // Load caches and groups from storage. If the request object - // is already in memory, the client is called immediately - // without returning to the message loop. - void LoadCache(int64 id, LoadClient* client); - void LoadOrCreateGroup(const GURL& manifest_url, - LoadClient* client); - - // Cancels pending callbacks for this client. - void CancelLoads(LoadClient* client); - - // Updates in memory and persistent storage. - void MarkAsForeignEntry(const GURL& entry_url, int64 cache_id); - - // The service generates unique storage ids for different object types. - int64 NewCacheId() { return ++last_cache_id_; } - int64 NewGroupId() { return ++last_group_id_; } - int64 NewEntryId() { return ++last_entry_id_; } - int64 NewResponseId() { return ++last_response_id_; } - - private: - // In-memory representation of stored appcache data. Represents a subset - // of the appcache database currently in use. - typedef base::hash_map<int64, AppCache*> CacheMap; - typedef std::map<GURL, AppCacheGroup*> GroupMap; - CacheMap caches_; - GroupMap groups_; - - // The last storage id used for different object types. - int64 last_cache_id_; - int64 last_group_id_; - int64 last_entry_id_; - int64 last_response_id_; + protected: + // Deals with persistence. + scoped_ptr<AppCacheStorage> storage_; // Track current processes. One 'backend' per child process. typedef std::map<int, AppCacheBackendImpl*> BackendMap; BackendMap backends_; - // Where we save our data. - FilePath cache_directory_; - // Context for use during cache updates. URLRequestContext* request_context_; - // TODO(michaeln): cache and group loading book keeping. - // TODO(michaeln): database and response storage // TODO(jennb): service state: e.g. reached quota? + + DISALLOW_COPY_AND_ASSIGN(AppCacheService); }; } // namespace appcache diff --git a/webkit/appcache/appcache_storage.h b/webkit/appcache/appcache_storage.h new file mode 100644 index 0000000..47d1af8 --- /dev/null +++ b/webkit/appcache/appcache_storage.h @@ -0,0 +1,178 @@ +// 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_STORAGE_H_ +#define WEBKIT_APPCACHE_APPCACHE_STORAGE_H_ + +#include <vector> + +#include "base/basictypes.h" +#include "base/logging.h" +#include "webkit/appcache/appcache_working_set.h" + +class GURL; + +namespace appcache { + +class AppCache; +class AppCacheGroup; +class AppCacheResponseInfo; +class AppCacheResponseReader; +class AppCacheResponseWriter; +class AppCacheService; + +class AppCacheStorage { + public: + + class Delegate { + public: + virtual ~Delegate() {} + + // If a load fails the 'cache' will be NULL. + virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) {} + + // If a load fails the 'group' will be NULL. + virtual void OnGroupLoaded( + AppCacheGroup* group, const GURL& manifest_url) {} + + // If successfully stored 'success' will be true. + virtual void OnGroupAndNewestCacheStored( + AppCacheGroup* group, bool success) {} + + // If the update fails, success will be false. + virtual void OnGroupMarkedAsObsolete(GURL& manifest_url, bool success) {} + + // If a load fails the 'response_info' will be NULL. + virtual void OnResponseInfoLoaded( + AppCacheResponseInfo* response_info, int64 response_id) {} + + // If no response is found, response_id will be kNoResponseId. + // If a response is found, the cache id and manifest url of the + // containing cache and group are also returned. + virtual void OnMainResponseFound( + const GURL& url, int64 response_id, bool is_fallback, + int64 cache_id, const GURL& mainfest_url) {} + }; + + explicit AppCacheStorage(AppCacheService* service) + : last_cache_id_(kUnitializedId), last_group_id_(kUnitializedId), + last_entry_id_(kUnitializedId), last_response_id_(kUnitializedId), + service_(service) {} + virtual ~AppCacheStorage() {} + + // Schedules a cache to be loaded from storage. Upon load completion + // the delegate will be called back. If the cache already resides in + // memory, the delegate will be called back immediately without returning + // to the message loop. If the load fails, the delegate will be called + // back with a NULL cache pointer. + virtual void LoadCache(int64 id, Delegate* delegate) = 0; + + // Schedules a group and its newest cache, if any, to be loaded from storage. + // Upon load completion the delegate will be called back. If the group + // and newest cache already reside in memory, the delegate will be called + // back immediately without returning to the message loop. If the load fails, + // the delegate will be called back with a NULL group pointer. + virtual void LoadOrCreateGroup( + const GURL& manifest_url, Delegate* delegate) = 0; + + // Schedules response info to be loaded from storage. + // Upon load completion the delegate will be called back. If the data + // already resides in memory, the delegate will be called back + // immediately without returning to the message loop. If the load fails, + // the delegate will be called back with a NULL pointer. + virtual void LoadResponseInfo( + const GURL& manifest_url, int64 response_id, Delegate* delegate) = 0; + + // Schedules a group and its newest complete cache to be initially stored or + // incrementally updated with new changes. Upon completion the delegate + // will be called back. A group without a newest cache cannot be stored. + // It's a programming error to call this method with such a group. A + // side effect of storing a new newest cache is the removal of the group's + // old caches and responses from persistent storage (although they may still + // linger in the in-memory working set until no longer needed). + virtual void StoreGroupAndNewestCache( + AppCacheGroup* group, Delegate* delegate) = 0; + + // Schedules a query to identify a response for a main request. Upon + // completion the delegate will be called back. + virtual void FindResponseForMainRequest( + const GURL& url, Delegate* delegate) = 0; + + // Immediately updates in-memory storage, if the cache is in memory, + // and schedules a task to update persistent storage. If the cache is + // already scheduled to be loaded, upon loading completion the entry + // will be marked. There is no delegate completion callback. + virtual void MarkEntryAsForeign(const GURL& entry_url, int64 cache_id) = 0; + + // Schedules a task to update persistent storage and doom the group and all + // related caches and responses for deletion. Upon completion the in-memory + // instance is marked as obsolete and the delegate callback is called. + virtual void MarkGroupAsObsolete( + AppCacheGroup* group, Delegate* delegate) = 0; + + // Cancels all pending callbacks for the delegate. The delegate callbacks + // will not be invoked after, however any scheduled operations will still + // take place. The callbacks for subsequently scheduled operations are + // unaffected. + virtual void CancelDelegateCallbacks(Delegate* delegate) = 0; + + // Creates a reader to read a response from storage. + virtual AppCacheResponseReader* CreateResponseReader( + const GURL& manifest_url, int64 response_id) = 0; + + // Creates a writer to write a new response to storage. This call + // establishes a new response id. + virtual AppCacheResponseWriter* CreateResponseWriter( + const GURL& manifest_url) = 0; + + // Schedules the deletion of many responses. + virtual void DoomResponses( + const GURL& manifest_url, const std::vector<int64>& response_ids) = 0; + + // Generates unique storage ids for different object types. + int64 NewCacheId() { + DCHECK(last_cache_id_ != kUnitializedId); + return ++last_cache_id_; + } + int64 NewGroupId() { + DCHECK(last_group_id_ != kUnitializedId); + return ++last_group_id_; + } + int64 NewEntryId() { + DCHECK(last_entry_id_ != kUnitializedId); + return ++last_entry_id_; + } + + // The working set of object instances currently in memory. + AppCacheWorkingSet* working_set() { return &working_set_; } + + // Simple ptr back to the service object that owns us. + AppCacheService* service() { return service_; } + + protected: + // Should only be called when creating a new response writer. + int64 NewResponseId() { + DCHECK(last_response_id_ != kUnitializedId); + return ++last_response_id_; + } + + // The last storage id used for different object types. + int64 last_cache_id_; + int64 last_group_id_; + int64 last_entry_id_; + int64 last_response_id_; + + AppCacheWorkingSet working_set_; + AppCacheService* service_; + + // The set of last ids must be retrieved from storage prior to being used. + static const int64 kUnitializedId = -1; + + DISALLOW_COPY_AND_ASSIGN(AppCacheStorage); +}; + +} // namespace appcache + +#endif // WEBKIT_APPCACHE_APPCACHE_STORAGE_H_ + diff --git a/webkit/appcache/appcache_storage_impl.cc b/webkit/appcache/appcache_storage_impl.cc new file mode 100644 index 0000000..3fb8280 --- /dev/null +++ b/webkit/appcache/appcache_storage_impl.cc @@ -0,0 +1,15 @@ +// 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. + +#include "webkit/appcache/appcache_storage_impl.h" + +namespace appcache { + +void AppCacheStorageImpl::Initialize(const FilePath& cache_directory) { + is_incognito_ = cache_directory.empty(); + cache_directory_ = cache_directory; + // TODO(michaeln): retrieve last_ids from storage +} + +} // namespace appcache diff --git a/webkit/appcache/appcache_storage_impl.h b/webkit/appcache/appcache_storage_impl.h new file mode 100644 index 0000000..ef75d1e --- /dev/null +++ b/webkit/appcache/appcache_storage_impl.h @@ -0,0 +1,28 @@ +// 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_STORAGE_IMPL_H_ +#define WEBKIT_APPCACHE_APPCACHE_STORAGE_IMPL_H_ + +#include "base/file_path.h" +#include "webkit/appcache/mock_appcache_storage.h" + +namespace appcache { + +// TODO(michaeln): write me, for now we derive from 'mock' storage. +class AppCacheStorageImpl : public MockAppCacheStorage { + public: + explicit AppCacheStorageImpl(AppCacheService* service) + : MockAppCacheStorage(service), is_incognito_(false) {} + + void Initialize(const FilePath& cache_directory); + + private: + bool is_incognito_; + FilePath cache_directory_; +}; + +} // namespace appcache + +#endif // WEBKIT_APPCACHE_APPCACHE_STORAGE_IMPL_H_ diff --git a/webkit/appcache/appcache_service_unittest.cc b/webkit/appcache/appcache_storage_unittest.cc index d142e8b..f5f9e06 100644 --- a/webkit/appcache/appcache_service_unittest.cc +++ b/webkit/appcache/appcache_storage_unittest.cc @@ -5,32 +5,33 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webkit/appcache/appcache.h" #include "webkit/appcache/appcache_group.h" -#include "webkit/appcache/appcache_service.h" +#include "webkit/appcache/appcache_storage.h" +#include "webkit/appcache/mock_appcache_service.h" namespace appcache { -class AppCacheServiceTest : public testing::Test { +class AppCacheStorageTest : public testing::Test { }; -TEST(AppCacheServiceTest, AddRemoveCache) { - AppCacheService service; +TEST(AppCacheStorageTest, AddRemoveCache) { + MockAppCacheService service; scoped_refptr<AppCache> cache = new AppCache(&service, 111); - service.RemoveCache(cache); + service.storage()->working_set()->RemoveCache(cache); // Removing non-existing cache from service should not fail. - AppCacheService dummy; - dummy.RemoveCache(cache); + MockAppCacheService dummy; + dummy.storage()->working_set()->RemoveCache(cache); } -TEST(AppCacheServiceTest, AddRemoveGroup) { - AppCacheService service; +TEST(AppCacheStorageTest, AddRemoveGroup) { + MockAppCacheService service; scoped_refptr<AppCacheGroup> group = new AppCacheGroup(&service, GURL::EmptyGURL()); - service.RemoveGroup(group); + service.storage()->working_set()->RemoveGroup(group); // Removing non-existing group from service should not fail. - AppCacheService dummy; - dummy.RemoveGroup(group); + MockAppCacheService dummy; + dummy.storage()->working_set()->RemoveGroup(group); } } // namespace appcache diff --git a/webkit/appcache/appcache_unittest.cc b/webkit/appcache/appcache_unittest.cc index 3d33358..12f8b30 100644 --- a/webkit/appcache/appcache_unittest.cc +++ b/webkit/appcache/appcache_unittest.cc @@ -6,7 +6,7 @@ #include "webkit/appcache/appcache.h" #include "webkit/appcache/appcache_frontend_impl.h" #include "webkit/appcache/appcache_host.h" -#include "webkit/appcache/appcache_service.h" +#include "webkit/appcache/mock_appcache_service.h" namespace appcache { @@ -14,23 +14,23 @@ class AppCacheTest : public testing::Test { }; TEST(AppCacheTest, CleanupUnusedCache) { - AppCacheService service; + MockAppCacheService service; AppCacheFrontendImpl frontend; - AppCache* cache = new AppCache(&service, 111); + scoped_refptr<AppCache> cache(new AppCache(&service, 111)); cache->set_complete(true); AppCacheHost host1(1, &frontend, &service); AppCacheHost host2(2, &frontend, &service); - host1.AssociateCache(cache); - host2.AssociateCache(cache); + host1.AssociateCache(cache.get()); + host2.AssociateCache(cache.get()); host1.AssociateCache(NULL); host2.AssociateCache(NULL); } TEST(AppCacheTest, AddModifyEntry) { - AppCacheService service; + MockAppCacheService service; scoped_refptr<AppCache> cache = new AppCache(&service, 111); const GURL kUrl1("http://foo.com"); @@ -51,7 +51,7 @@ TEST(AppCacheTest, AddModifyEntry) { } TEST(AppCacheTest, InitializeWithManifest) { - AppCacheService service; + MockAppCacheService service; scoped_refptr<AppCache> cache = new AppCache(&service, 1234); EXPECT_TRUE(cache->fallback_namespaces_.empty()); diff --git a/webkit/appcache/appcache_update_job.cc b/webkit/appcache/appcache_update_job.cc index 0834039..d9cf729 100644 --- a/webkit/appcache/appcache_update_job.cc +++ b/webkit/appcache/appcache_update_job.cc @@ -344,7 +344,8 @@ void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) { // Proceed with update process. Section 6.9.4 steps 8-20. internal_state_ = DOWNLOADING; - inprogress_cache_ = new AppCache(service_, service_->NewCacheId()); + inprogress_cache_ = new AppCache(service_, + service_->storage()->NewCacheId()); inprogress_cache_->set_owning_group(group_); BuildUrlFileList(manifest); inprogress_cache_->InitializeWithManifest(&manifest); diff --git a/webkit/appcache/appcache_update_job_unittest.cc b/webkit/appcache/appcache_update_job_unittest.cc index 00fc819..5dd1536 100644 --- a/webkit/appcache/appcache_update_job_unittest.cc +++ b/webkit/appcache/appcache_update_job_unittest.cc @@ -11,8 +11,8 @@ #include "net/url_request/url_request_unittest.h" #include "webkit/appcache/appcache_group.h" #include "webkit/appcache/appcache_host.h" -#include "webkit/appcache/appcache_service.h" #include "webkit/appcache/appcache_update_job.h" +#include "webkit/appcache/mock_appcache_service.h" namespace appcache { class AppCacheUpdateJobTest; @@ -617,7 +617,7 @@ class AppCacheUpdateJobTest : public testing::Test, AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); group_->update_job_ = update; - AppCache* cache = MakeCacheForGroup(service_->NewCacheId()); + AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId()); MockFrontend* frontend1 = MakeMockFrontend(); MockFrontend* frontend2 = MakeMockFrontend(); AppCacheHost* host1 = MakeHost(1, frontend1); @@ -662,7 +662,7 @@ class AppCacheUpdateJobTest : public testing::Test, AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); group_->update_job_ = update; - AppCache* cache = MakeCacheForGroup(service_->NewCacheId()); + AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId()); MockFrontend* frontend1 = MakeMockFrontend(); MockFrontend* frontend2 = MakeMockFrontend(); AppCacheHost* host1 = MakeHost(1, frontend1); @@ -738,7 +738,7 @@ class AppCacheUpdateJobTest : public testing::Test, AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); group_->update_job_ = update; - AppCache* cache = MakeCacheForGroup(service_->NewCacheId()); + AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId()); MockFrontend* frontend1 = MakeMockFrontend(); MockFrontend* frontend2 = MakeMockFrontend(); AppCacheHost* host1 = MakeHost(1, frontend1); @@ -784,7 +784,7 @@ class AppCacheUpdateJobTest : public testing::Test, AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); group_->update_job_ = update; - AppCache* cache = MakeCacheForGroup(service_->NewCacheId()); + AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId()); MockFrontend* frontend1 = MakeMockFrontend(); MockFrontend* frontend2 = MakeMockFrontend(); AppCacheHost* host1 = MakeHost(1, frontend1); @@ -858,7 +858,7 @@ class AppCacheUpdateJobTest : public testing::Test, AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); group_->update_job_ = update; - AppCache* cache = MakeCacheForGroup(service_->NewCacheId()); + AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId()); MockFrontend* frontend1 = MakeMockFrontend(); MockFrontend* frontend2 = MakeMockFrontend(); AppCacheHost* host1 = MakeHost(1, frontend1); @@ -1048,14 +1048,18 @@ class AppCacheUpdateJobTest : public testing::Test, void OnUpdateComplete(AppCacheGroup* group) { ASSERT_EQ(group_, group); + UpdateFinished(); + } - // Finish up outside of observer callback so that group can be deleted. + void UpdateFinished() { + // We unwind the stack prior to finishing up to let stack + // based objects get deleted. MessageLoop::current()->PostTask(FROM_HERE, method_factory_.NewRunnableMethod( - &AppCacheUpdateJobTest::UpdateFinished)); + &AppCacheUpdateJobTest::UpdateFinishedUnwound)); } - void UpdateFinished() { + void UpdateFinishedUnwound() { EXPECT_EQ(AppCacheGroup::IDLE, group_->update_status()); EXPECT_TRUE(group_->update_job() == NULL); if (do_checks_after_update_finished_) @@ -1073,7 +1077,7 @@ class AppCacheUpdateJobTest : public testing::Test, } void MakeService() { - service_.reset(new AppCacheService()); + service_.reset(new MockAppCacheService()); request_context_ = new TestURLRequestContext(); service_->set_request_context(request_context_); } @@ -1273,7 +1277,7 @@ class AppCacheUpdateJobTest : public testing::Test, static scoped_refptr<HTTPTestServer> http_server_; ScopedRunnableMethodFactory<AppCacheUpdateJobTest> method_factory_; - scoped_ptr<AppCacheService> service_; + scoped_ptr<MockAppCacheService> service_; scoped_refptr<TestURLRequestContext> request_context_; scoped_refptr<AppCacheGroup> group_; scoped_ptr<base::WaitableEvent> event_; @@ -1301,7 +1305,7 @@ scoped_ptr<base::Thread> AppCacheUpdateJobTest::io_thread_; scoped_refptr<HTTPTestServer> AppCacheUpdateJobTest::http_server_; TEST_F(AppCacheUpdateJobTest, AlreadyChecking) { - AppCacheService service; + MockAppCacheService service; scoped_refptr<AppCacheGroup> group = new AppCacheGroup(&service, GURL("http://manifesturl.com")); @@ -1328,7 +1332,7 @@ TEST_F(AppCacheUpdateJobTest, AlreadyChecking) { } TEST_F(AppCacheUpdateJobTest, AlreadyDownloading) { - AppCacheService service; + MockAppCacheService service; scoped_refptr<AppCacheGroup> group = new AppCacheGroup(&service, GURL("http://manifesturl.com")); diff --git a/webkit/appcache/appcache_working_set.cc b/webkit/appcache/appcache_working_set.cc new file mode 100644 index 0000000..a5b544f --- /dev/null +++ b/webkit/appcache/appcache_working_set.cc @@ -0,0 +1,38 @@ +// 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. + +#include "webkit/appcache/appcache_working_set.h" + +#include "base/logging.h" +#include "webkit/appcache/appcache.h" +#include "webkit/appcache/appcache_group.h" + +namespace appcache { + +AppCacheWorkingSet::~AppCacheWorkingSet() { + DCHECK(caches_.empty()); + DCHECK(groups_.empty()); +} + +void AppCacheWorkingSet::AddCache(AppCache* cache) { + int64 cache_id = cache->cache_id(); + DCHECK(caches_.find(cache_id) == caches_.end()); + caches_.insert(CacheMap::value_type(cache_id, cache)); +} + +void AppCacheWorkingSet::RemoveCache(AppCache* cache) { + caches_.erase(cache->cache_id()); +} + +void AppCacheWorkingSet::AddGroup(AppCacheGroup* group) { + const GURL& url = group->manifest_url(); + DCHECK(groups_.find(url) == groups_.end()); + groups_.insert(GroupMap::value_type(url, group)); +} + +void AppCacheWorkingSet::RemoveGroup(AppCacheGroup* group) { + groups_.erase(group->manifest_url()); +} + +} // namespace diff --git a/webkit/appcache/appcache_working_set.h b/webkit/appcache/appcache_working_set.h new file mode 100644 index 0000000..6785d50 --- /dev/null +++ b/webkit/appcache/appcache_working_set.h @@ -0,0 +1,57 @@ +// 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_WORKING_SET_H_ +#define WEBKIT_APPCACHE_APPCACHE_WORKING_SET_H_ + +#include <map> + +#include "base/hash_tables.h" +#include "googleurl/src/gurl.h" + +namespace appcache { + +class AppCache; +class AppCacheGroup; +class AppCacheResponseInfo; + +// Represents the working set of appcache object instances +// currently in memory. +class AppCacheWorkingSet { + public: + ~AppCacheWorkingSet(); + + void AddCache(AppCache* cache); + void RemoveCache(AppCache* cache); + AppCache* GetCache(int64 id) { + CacheMap::iterator it = caches_.find(id); + return (it != caches_.end()) ? it->second : NULL; + } + + void AddGroup(AppCacheGroup* group); + void RemoveGroup(AppCacheGroup* group); + AppCacheGroup* GetGroup(const GURL& manifest_url) { + GroupMap::iterator it = groups_.find(manifest_url); + return (it != groups_.end()) ? it->second : NULL; + } + + void AddResponseInfo(AppCacheResponseInfo* response_info); + void RemoveResponseInfo(AppCacheResponseInfo* response_info); + AppCacheResponseInfo* GetResponseInfo(int64 id) { + ResponseInfoMap::iterator it = response_infos_.find(id); + return (it != response_infos_.end()) ? it->second : NULL; + } + + private: + typedef base::hash_map<int64, AppCache*> CacheMap; + typedef std::map<GURL, AppCacheGroup*> GroupMap; + typedef base::hash_map<int64, AppCacheResponseInfo*> ResponseInfoMap; + CacheMap caches_; + GroupMap groups_; + ResponseInfoMap response_infos_; +}; + +} // namespace appcache + +#endif // WEBKIT_APPCACHE_APPCACHE_WORKING_SET_H_ diff --git a/webkit/appcache/mock_appcache_service.h b/webkit/appcache/mock_appcache_service.h new file mode 100644 index 0000000..705dc0e --- /dev/null +++ b/webkit/appcache/mock_appcache_service.h @@ -0,0 +1,24 @@ +// 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_MOCK_APPCACHE_SERVICE_H_ +#define WEBKIT_APPCACHE_MOCK_APPCACHE_SERVICE_H_ + +#include "base/compiler_specific.h" +#include "webkit/appcache/appcache_service.h" +#include "webkit/appcache/mock_appcache_storage.h" + +namespace appcache { + +// For use by unit tests. +class MockAppCacheService : public AppCacheService { + public: + MockAppCacheService() { + storage_.reset(new MockAppCacheStorage(this)); + } +}; + +} // namespace appcache + +#endif // WEBKIT_APPCACHE_MOCK_APPCACHE_SERVICE_H_ diff --git a/webkit/appcache/mock_appcache_storage.cc b/webkit/appcache/mock_appcache_storage.cc new file mode 100644 index 0000000..4dfb8c9 --- /dev/null +++ b/webkit/appcache/mock_appcache_storage.cc @@ -0,0 +1,98 @@ +// 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. + +#include "webkit/appcache/mock_appcache_storage.h" + +#include "base/logging.h" +#include "base/ref_counted.h" +#include "webkit/appcache/appcache.h" +#include "webkit/appcache/appcache_backend_impl.h" +#include "webkit/appcache/appcache_entry.h" +#include "webkit/appcache/appcache_group.h" +#include "webkit/appcache/appcache_response.h" + +namespace appcache { + +MockAppCacheStorage::MockAppCacheStorage(AppCacheService* service) + : AppCacheStorage(service) { + last_cache_id_ = 0; + last_entry_id_ = 0; + last_group_id_ = 0; + last_response_id_ = 0; +} + +void MockAppCacheStorage::LoadCache(int64 id, Delegate* delegate) { + AppCache* cache = working_set_.GetCache(id); + delegate->OnCacheLoaded(cache, id); +} + +void MockAppCacheStorage::LoadOrCreateGroup( + const GURL& manifest_url, Delegate* delegate) { + scoped_refptr<AppCacheGroup> group = working_set_.GetGroup(manifest_url); + if (!group.get()) { + group = new AppCacheGroup(service_, manifest_url); + DCHECK(working_set_.GetGroup(manifest_url)); + } + delegate->OnGroupLoaded(group.get(), manifest_url); +} + +void MockAppCacheStorage::LoadResponseInfo( + const GURL& manifest_url, int64 id, Delegate* delegate) { + delegate->OnResponseInfoLoaded(working_set_.GetResponseInfo(id), id); +} + +void MockAppCacheStorage::StoreGroupAndNewestCache( + AppCacheGroup* group, Delegate* delegate) { + // TODO(michaeln): write me + delegate->OnGroupAndNewestCacheStored(group, false); +} + +void MockAppCacheStorage::FindResponseForMainRequest( + const GURL& url, Delegate* delegate) { + // TODO(michaeln): write me + delegate->OnMainResponseFound( + url, kNoResponseId, false, kNoCacheId, GURL::EmptyGURL()); +} + +void MockAppCacheStorage::MarkEntryAsForeign( + const GURL& entry_url, int64 cache_id) { + // Update the working set. + AppCache* cache = working_set_.GetCache(cache_id); + if (cache) { + AppCacheEntry* entry = cache->GetEntry(entry_url); + DCHECK(entry); + if (entry) + entry->add_types(AppCacheEntry::FOREIGN); + } + // TODO(michaeln): actually update in storage, and if this cache is + // being loaded be sure to update the memory cache upon load completion. +} + +void MockAppCacheStorage::MarkGroupAsObsolete( + AppCacheGroup* group, Delegate* delegate) { + // TODO(michaeln): write me +} + +void MockAppCacheStorage::CancelDelegateCallbacks(Delegate* delegate) { + // TODO(michaeln): remove delegate from callback list +} + +AppCacheResponseReader* MockAppCacheStorage::CreateResponseReader( + const GURL& origin, int64 response_id) { + return new AppCacheResponseReader(response_id, NULL); + // TODO(michaeln): use a disk_cache +} + +AppCacheResponseWriter* MockAppCacheStorage::CreateResponseWriter( + const GURL& manifest_url) { + return new AppCacheResponseWriter(NewResponseId(), NULL); + // TODO(michaeln): use a disk_cache +} + +void MockAppCacheStorage::DoomResponses( + const GURL& manifest_url, const std::vector<int64>& response_ids) { + // TODO(michaeln): write me +} + +} // namespace appcache diff --git a/webkit/appcache/mock_appcache_storage.h b/webkit/appcache/mock_appcache_storage.h new file mode 100644 index 0000000..95cc082 --- /dev/null +++ b/webkit/appcache/mock_appcache_storage.h @@ -0,0 +1,38 @@ +// 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_MOCK_APPCACHE_STORAGE_H_ +#define WEBKIT_APPCACHE_MOCK_APPCACHE_STORAGE_H_ + +#include "webkit/appcache/appcache_storage.h" + +namespace appcache { + +// For use in unit tests. +// Note: This class is also being used to bootstrap our development efforts. +// We can get layout tests up and running, and back fill with real storage +// somewhat in parallel. +class MockAppCacheStorage : public AppCacheStorage { + public: + explicit MockAppCacheStorage(AppCacheService* service); + virtual void LoadCache(int64 id, Delegate* delegate); + virtual void LoadOrCreateGroup(const GURL& manifest_url, Delegate* delegate); + virtual void LoadResponseInfo( + const GURL& manifest_url, int64 response_id, Delegate* delegate); + virtual void StoreGroupAndNewestCache( + AppCacheGroup* group, Delegate* delegate); + virtual void FindResponseForMainRequest(const GURL& url, Delegate* delegate); + virtual void CancelDelegateCallbacks(Delegate* delegate); + virtual void MarkEntryAsForeign(const GURL& entry_url, int64 cache_id); + virtual void MarkGroupAsObsolete(AppCacheGroup* group, Delegate* delegate); + virtual AppCacheResponseReader* CreateResponseReader( + const GURL& manifest_url, int64 response_id); + virtual AppCacheResponseWriter* CreateResponseWriter(const GURL& origin); + virtual void DoomResponses( + const GURL& manifest_url, const std::vector<int64>& response_ids); +}; + +} // namespace appcache + +#endif // WEBKIT_APPCACHE_MOCK_APPCACHE_STORAGE_H_ |