summaryrefslogtreecommitdiffstats
path: root/webkit/appcache
diff options
context:
space:
mode:
authormichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-01 22:30:30 +0000
committermichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-01 22:30:30 +0000
commit23f1ef1a445a53bcefc8ddab9f4184b1db7321c5 (patch)
treec9f17a33025ed5b5c5dee76a7b4fef9104e9a995 /webkit/appcache
parente143c823ce66af5a83a9a17b6f5938eb16e49392 (diff)
downloadchromium_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.cc48
-rw-r--r--webkit/appcache/appcache_backend_impl.h44
-rw-r--r--webkit/appcache/appcache_host.h4
-rw-r--r--webkit/appcache/appcache_interceptor.cc125
-rw-r--r--webkit/appcache/appcache_interceptor.h60
-rw-r--r--webkit/appcache/appcache_service.cc15
-rw-r--r--webkit/appcache/appcache_service.h27
-rw-r--r--webkit/appcache/web_application_cache_host_impl.cc1
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,