diff options
author | michaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-01 22:30:30 +0000 |
---|---|---|
committer | michaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-01 22:30:30 +0000 |
commit | 23f1ef1a445a53bcefc8ddab9f4184b1db7321c5 (patch) | |
tree | c9f17a33025ed5b5c5dee76a7b4fef9104e9a995 /webkit/appcache | |
parent | e143c823ce66af5a83a9a17b6f5938eb16e49392 (diff) | |
download | chromium_src-23f1ef1a445a53bcefc8ddab9f4184b1db7321c5.zip chromium_src-23f1ef1a445a53bcefc8ddab9f4184b1db7321c5.tar.gz chromium_src-23f1ef1a445a53bcefc8ddab9f4184b1db7321c5.tar.bz2 |
Plumb request interception into the appcache library for both chrome and test_shell.
AppCache library:
* Added AppCacheInterceptor, which is derived from URLRequest::Interceptor.
Chrome:
* Each UserProfile instantiates a ChromeAppCacheService, which is derived from an appcache library class.
* Each ChromeURLRequestContext associated with that profile has a reference to that instance.
* ResourceDispatcherHost pokes AppCacheInterceptor when initiating URLRequests and when returning the response head.
TestShell:
* Added SimpleAppCacheSystem which bundles together appcache lib components for use in a single process with an UI and IO thread.
* TestShellWebKit instantiates and initializes an instance of the above, aimed at at temp directory that will get cleaned up when the test run is over.
* SimpleResourceLoaderBridge pokes the system when initiating URLRequests and when returning the response head.
TEST=none, although many existing tests exercise this stuff
BUG=none
Review URL: http://codereview.chromium.org/173406
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25099 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/appcache')
-rw-r--r-- | webkit/appcache/appcache_backend_impl.cc | 48 | ||||
-rw-r--r-- | webkit/appcache/appcache_backend_impl.h | 44 | ||||
-rw-r--r-- | webkit/appcache/appcache_host.h | 4 | ||||
-rw-r--r-- | webkit/appcache/appcache_interceptor.cc | 125 | ||||
-rw-r--r-- | webkit/appcache/appcache_interceptor.h | 60 | ||||
-rw-r--r-- | webkit/appcache/appcache_service.cc | 15 | ||||
-rw-r--r-- | webkit/appcache/appcache_service.h | 27 | ||||
-rw-r--r-- | webkit/appcache/web_application_cache_host_impl.cc | 1 |
8 files changed, 291 insertions, 33 deletions
diff --git a/webkit/appcache/appcache_backend_impl.cc b/webkit/appcache/appcache_backend_impl.cc index 1c0cfc7..82b40ee 100644 --- a/webkit/appcache/appcache_backend_impl.cc +++ b/webkit/appcache/appcache_backend_impl.cc @@ -4,29 +4,34 @@ #include "webkit/appcache/appcache_backend_impl.h" -#include "base/logging.h" +#include "webkit/appcache/appcache_host.h" +#include "webkit/appcache/appcache_service.h" #include "webkit/appcache/web_application_cache_host_impl.h" namespace appcache { AppCacheBackendImpl::~AppCacheBackendImpl() { - // TODO(michaeln): if (service_) service_->UnregisterFrontend(frontend_); + if (service_) + service_->UnregisterBackend(this); } void AppCacheBackendImpl::Initialize(AppCacheService* service, - AppCacheFrontend* frontend) { - DCHECK(!service_ && !frontend_ && frontend); // DCHECK(service) + AppCacheFrontend* frontend, + int process_id) { + DCHECK(!service_ && !frontend_ && frontend && service); service_ = service; frontend_ = frontend; - // TODO(michaeln): service_->RegisterFrontend(frontend_); + process_id_ = process_id; + service_->RegisterBackend(this); } -void AppCacheBackendImpl::RegisterHost(int host_id) { - // TODO(michaeln): plumb to service +void AppCacheBackendImpl::RegisterHost(int id) { + DCHECK(hosts_.find(id) == hosts_.end()); + hosts_.insert(HostMap::value_type(id, AppCacheHost(id, frontend_))); } -void AppCacheBackendImpl::UnregisterHost(int host_id) { - // TODO(michaeln): plumb to service +void AppCacheBackendImpl::UnregisterHost(int id) { + hosts_.erase(id); } void AppCacheBackendImpl::SelectCache( @@ -34,7 +39,7 @@ void AppCacheBackendImpl::SelectCache( const GURL& document_url, const int64 cache_document_was_loaded_from, const GURL& manifest_url) { - // TODO(michaeln): plumb to service + // TODO(michaeln): write me frontend_->OnCacheSelected(host_id, kNoCacheId, UNCACHED); } @@ -42,22 +47,25 @@ void AppCacheBackendImpl::MarkAsForeignEntry( int host_id, const GURL& document_url, int64 cache_document_was_loaded_from) { - // TODO(michaeln): plumb to service + // TODO(michaeln): write me } -Status AppCacheBackendImpl::GetStatus(int host_id) { - // TODO(michaeln): plumb to service - return UNCACHED; +void AppCacheBackendImpl::GetStatusWithCallback( + int host_id, GetStatusCallback* callback, void* callback_param) { + // TODO(michaeln): write me + callback->Run(UNCACHED, callback_param); } -bool AppCacheBackendImpl::StartUpdate(int host_id) { - // TODO(michaeln): plumb to service - return false; +void AppCacheBackendImpl::StartUpdateWithCallback( + int host_id, StartUpdateCallback* callback, void* callback_param) { + // TODO(michaeln): write me + callback->Run(false, callback_param); } -bool AppCacheBackendImpl::SwapCache(int host_id) { - // TODO(michaeln): plumb to service - return false; +void AppCacheBackendImpl::SwapCacheWithCallback( + int host_id, SwapCacheCallback* callback, void* callback_param) { + // TODO(michaeln): write me + callback->Run(false, callback_param); } } // namespace appcache diff --git a/webkit/appcache/appcache_backend_impl.h b/webkit/appcache/appcache_backend_impl.h index 93a7083..abf4247 100644 --- a/webkit/appcache/appcache_backend_impl.h +++ b/webkit/appcache/appcache_backend_impl.h @@ -5,20 +5,42 @@ #ifndef WEBKIT_APPCACHE_APPCACHE_BACKEND_IMPL_H_ #define WEBKIT_APPCACHE_APPCACHE_BACKEND_IMPL_H_ +#include <map> + +#include "base/logging.h" +#include "base/task.h" +#include "webkit/appcache/appcache_host.h" #include "webkit/appcache/appcache_interfaces.h" namespace appcache { class AppCacheService; +typedef Callback2<Status, void*>::Type GetStatusCallback; +typedef Callback2<bool, void*>::Type StartUpdateCallback; +typedef Callback2<bool, void*>::Type SwapCacheCallback; + class AppCacheBackendImpl : public AppCacheBackend { public: - AppCacheBackendImpl() : service_(NULL), frontend_(NULL) {} + AppCacheBackendImpl() : service_(NULL), frontend_(NULL), process_id_(0) {} ~AppCacheBackendImpl(); void Initialize(AppCacheService* service, - AppCacheFrontend* frontend); + AppCacheFrontend* frontend, + int process_id); + + int process_id() const { return process_id_; } + + // Returns a pointer to a registered host. The backend retains ownership. + AppCacheHost* GetHost(int host_id) { + HostMap::iterator it = hosts_.find(host_id); + return (it != hosts_.end()) ? &(it->second) : NULL; + } + typedef std::map<int, AppCacheHost> HostMap; + const HostMap& hosts() { return hosts_; } + + // AppCacheBackend methods virtual void RegisterHost(int host_id); virtual void UnregisterHost(int host_id); virtual void SelectCache(int host_id, @@ -27,13 +49,25 @@ class AppCacheBackendImpl : public AppCacheBackend { const GURL& manifest_url); virtual void MarkAsForeignEntry(int host_id, const GURL& document_url, int64 cache_document_was_loaded_from); - virtual Status GetStatus(int host_id); - virtual bool StartUpdate(int host_id); - virtual bool SwapCache(int host_id); + + // We don't use the sync variants in the backend, would block the IO thread. + virtual Status GetStatus(int host_id) { NOTREACHED(); return UNCACHED; } + virtual bool StartUpdate(int host_id) { NOTREACHED(); return false; } + virtual bool SwapCache(int host_id) { NOTREACHED(); return false; } + + // Async variants of the sync methods defined in the backend interface. + void GetStatusWithCallback(int host_id, GetStatusCallback* callback, + void* callback_param); + void StartUpdateWithCallback(int host_id, StartUpdateCallback* callback, + void* callback_param); + void SwapCacheWithCallback(int host_id, SwapCacheCallback* callback, + void* callback_param); private: AppCacheService* service_; AppCacheFrontend* frontend_; + int process_id_; + HostMap hosts_; }; } // namespace diff --git a/webkit/appcache/appcache_host.h b/webkit/appcache/appcache_host.h index 439e042..bebc22d 100644 --- a/webkit/appcache/appcache_host.h +++ b/webkit/appcache/appcache_host.h @@ -24,6 +24,10 @@ class AppCacheHost { selected_cache_ = cache; } + bool is_selection_pending() { + return false; // TODO(michaeln) + } + private: // identifies the corresponding appcache host in the child process int host_id_; diff --git a/webkit/appcache/appcache_interceptor.cc b/webkit/appcache/appcache_interceptor.cc new file mode 100644 index 0000000..a66fea8 --- /dev/null +++ b/webkit/appcache/appcache_interceptor.cc @@ -0,0 +1,125 @@ +// 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_interceptor.h" + +#include "webkit/appcache/appcache_backend_impl.h" +#include "webkit/appcache/appcache_host.h" +#include "webkit/appcache/appcache_interfaces.h" +#include "webkit/appcache/appcache_service.h" + +namespace appcache { + +// Extra info we associate with requests for use at MaybeIntercept time. This +// info is deleted when the URLRequest is deleted which occurs after the +// request is complete and all data has been read. +struct AppCacheInterceptor::ExtraInfo : public URLRequest::UserData { + // Inputs, extra request info + AppCacheService* service; + int process_id; + int host_id; + ResourceType::Type resource_type; + + // Outputs, extra response info + int64 cache_id; + GURL manifest_url; + + // The host associated with the request + // TODO(michaeln): Be careful with this data member, its not clear + // if a URLRequest can outlive the associated host. As we get further + // along, we'll need to notify reqeust waiting on cache selection to + // allow them to continue upon completion of selection. But we also need + // to handle navigating away from the page away prior to selection being + // complete. + AppCacheHost* host_; + + ExtraInfo(AppCacheService* service, int process_id, int host_id, + ResourceType::Type resource_type, AppCacheHost* host) + : service(service), process_id(process_id), host_id(host_id), + resource_type(resource_type), cache_id(kNoCacheId), host_(host) { + } + + static void SetInfo(URLRequest* request, ExtraInfo* info) { + request->SetUserData(instance(), info); // request takes ownership + } + + static ExtraInfo* GetInfo(URLRequest* request) { + return static_cast<ExtraInfo*>(request->GetUserData(instance())); + } +}; + +static bool IsMainRequest(ResourceType::Type type) { + // TODO(michaeln): SHARED_WORKER type? + return ResourceType::IsFrame(type); +} + +void AppCacheInterceptor::SetExtraRequestInfo( + URLRequest* request, AppCacheService* service, int process_id, + int host_id, ResourceType::Type resource_type) { + if (service && (host_id != kNoHostId)) { + AppCacheHost* host = service->GetBackend(process_id)->GetHost(host_id); + DCHECK(host); + if (IsMainRequest(resource_type) || host->selected_cache() || + host->is_selection_pending()) { + ExtraInfo* info = new ExtraInfo(service, process_id, + host_id, resource_type, host); + ExtraInfo::SetInfo(request, info); + } + } +} + +void AppCacheInterceptor::GetExtraResponseInfo(URLRequest* request, + int64* cache_id, + GURL* manifest_url) { + ExtraInfo* info = ExtraInfo::GetInfo(request); + if (info) { + // TODO(michaeln): If this is a main request and it was retrieved from + // an appcache, ensure that appcache survives the frame navigation. The + // AppCacheHost should hold reference to that cache to prevent it from + // being dropped from the in-memory collection of AppCaches. When cache + // selection occurs, that extra reference should be dropped. + *cache_id = info->cache_id; + *manifest_url = info->manifest_url; + } else { + DCHECK(*cache_id == kNoCacheId); + DCHECK(manifest_url->is_empty()); + } +} + +AppCacheInterceptor::AppCacheInterceptor() { + URLRequest::RegisterRequestInterceptor(this); +} + +AppCacheInterceptor::~AppCacheInterceptor() { + URLRequest::UnregisterRequestInterceptor(this); +} + +URLRequestJob* AppCacheInterceptor::MaybeIntercept(URLRequest* request) { + ExtraInfo* info = ExtraInfo::GetInfo(request); + if (!info) + return NULL; + // TODO(michaeln): write me + return NULL; +} + +URLRequestJob* AppCacheInterceptor::MaybeInterceptRedirect( + URLRequest* request, + const GURL& location) { + ExtraInfo* info = ExtraInfo::GetInfo(request); + if (!info) + return NULL; + // TODO(michaeln): write me + return NULL; +} + +URLRequestJob* AppCacheInterceptor::MaybeInterceptResponse( + URLRequest* request) { + ExtraInfo* info = ExtraInfo::GetInfo(request); + if (!info) + return NULL; + // TODO(michaeln): write me + return NULL; +} + +} // namespace appcache diff --git a/webkit/appcache/appcache_interceptor.h b/webkit/appcache/appcache_interceptor.h new file mode 100644 index 0000000..51b9a89 --- /dev/null +++ b/webkit/appcache/appcache_interceptor.h @@ -0,0 +1,60 @@ +// 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_INTERCEPTOR_H_ +#define WEBKIT_APPCACHE_APPCACHE_INTERCEPTOR_H_ + +#include "base/singleton.h" +#include "googleurl/src/gurl.h" +#include "net/url_request/url_request.h" +#include "webkit/glue/resource_type.h" + +namespace appcache { + +class AppCacheService; + +// An interceptor to hijack requests and potentially service them out of +// the appcache. +class AppCacheInterceptor : public URLRequest::Interceptor { + public: + // Registers a singleton instance with the net library. + // Should be called early in the IO thread prior to initiating requests. + static void EnsureRegistered() { + CHECK(instance()); + } + + // Must be called to make a request eligible for retrieval from an appcache. + static void SetExtraRequestInfo(URLRequest* request, + AppCacheService* service, + int process_id, + int host_id, + ResourceType::Type resource_type); + + // May be called after response headers are complete to retrieve extra + // info about the response. + static void GetExtraResponseInfo(URLRequest* request, + int64* cache_id, + GURL* manifest_url); + + protected: + // URLRequest::Interceptor overrides + virtual URLRequestJob* MaybeIntercept(URLRequest* request); + virtual URLRequestJob* MaybeInterceptResponse(URLRequest* request); + virtual URLRequestJob* MaybeInterceptRedirect(URLRequest* request, + const GURL& location); + + private: + friend struct DefaultSingletonTraits<AppCacheInterceptor>; + static AppCacheInterceptor* instance() { + return Singleton<AppCacheInterceptor>::get(); + } + struct ExtraInfo; + AppCacheInterceptor(); + virtual ~AppCacheInterceptor(); + DISALLOW_COPY_AND_ASSIGN(AppCacheInterceptor); +}; + +} // namespace appcache + +#endif // WEBKIT_APPCACHE_APPCACHE_INTERCEPTOR_H_ diff --git a/webkit/appcache/appcache_service.cc b/webkit/appcache/appcache_service.cc index 0d3579b..0fd5356 100644 --- a/webkit/appcache/appcache_service.cc +++ b/webkit/appcache/appcache_service.cc @@ -17,14 +17,21 @@ AppCacheService::~AppCacheService() { DCHECK(groups_.empty()); } -void AppCacheService::RegisterBackendImpl( +void AppCacheService::Initialize(const FilePath& cache_directory) { + // An empty cache directory indicates chrome incognito. + cache_directory_ = cache_directory; +} + +void AppCacheService::RegisterBackend( AppCacheBackendImpl* backend_impl) { - backends_.insert(backend_impl); + DCHECK(backends_.find(backend_impl->process_id()) == backends_.end()); + backends_.insert( + BackendMap::value_type(backend_impl->process_id(), backend_impl)); } -void AppCacheService::UnregisterBackendImpl( +void AppCacheService::UnregisterBackend( AppCacheBackendImpl* backend_impl) { - backends_.erase(backend_impl); + backends_.erase(backend_impl->process_id()); } void AppCacheService::AddCache(AppCache* cache) { diff --git a/webkit/appcache/appcache_service.h b/webkit/appcache/appcache_service.h index 3eaa43d..bc8bee8 100644 --- a/webkit/appcache/appcache_service.h +++ b/webkit/appcache/appcache_service.h @@ -10,6 +10,7 @@ #include <vector> #include "base/hash_tables.h" +#include "base/file_path.h" #include "googleurl/src/gurl.h" namespace appcache { @@ -24,17 +25,34 @@ class AppCacheService { public: virtual ~AppCacheService(); + void Initialize(const FilePath& cache_directory); + // TODO(jennb): API to set service settings, like file paths for storage // track which processes are using this appcache service - void RegisterBackendImpl(AppCacheBackendImpl* backend_impl); - void UnregisterBackendImpl(AppCacheBackendImpl* backend_impl); + void RegisterBackend(AppCacheBackendImpl* backend_impl); + void UnregisterBackend(AppCacheBackendImpl* backend_impl); void AddCache(AppCache* cache); void RemoveCache(AppCache* cache); void AddGroup(AppCacheGroup* group); void RemoveGroup(AppCacheGroup* group); + AppCacheBackendImpl* GetBackend(int id) { + BackendMap::iterator it = backends_.find(id); + return (it != backends_.end()) ? it->second : NULL; + } + + 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; + } + private: // In-memory representation of stored appcache data. Represents a subset // of the appcache database currently in use. @@ -44,9 +62,10 @@ class AppCacheService { GroupMap groups_; // Track current processes. One 'backend' per child process. - typedef std::set<AppCacheBackendImpl*> BackendSet; - BackendSet backends_; + typedef std::map<int, AppCacheBackendImpl*> BackendMap; + BackendMap backends_; + FilePath cache_directory_; // TODO(jennb): info about appcache storage // AppCacheDatabase db_; // DiskCache response_storage_; diff --git a/webkit/appcache/web_application_cache_host_impl.cc b/webkit/appcache/web_application_cache_host_impl.cc index 02a698f..d5d50fb 100644 --- a/webkit/appcache/web_application_cache_host_impl.cc +++ b/webkit/appcache/web_application_cache_host_impl.cc @@ -43,6 +43,7 @@ WebApplicationCacheHostImpl::WebApplicationCacheHostImpl( WebApplicationCacheHostImpl::~WebApplicationCacheHostImpl() { backend_->UnregisterHost(host_id_); + all_hosts.Remove(host_id_); } void WebApplicationCacheHostImpl::OnCacheSelected(int64 selected_cache_id, |