summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authormichaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-04 00:34:19 +0000
committermichaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-04 00:34:19 +0000
commit5fcb289ebad2277b30a19927098f8032dadb5dd1 (patch)
tree1bfcf3d665d2e10b1441cbeb0820609cfb2ef4bb /webkit
parent86e75f009ef286aed6f7a534f49db57bc08239a7 (diff)
downloadchromium_src-5fcb289ebad2277b30a19927098f8032dadb5dd1.zip
chromium_src-5fcb289ebad2277b30a19927098f8032dadb5dd1.tar.gz
chromium_src-5fcb289ebad2277b30a19927098f8032dadb5dd1.tar.bz2
Transfer appcache state during cross site navigations too.
The AppCacheHost is an object that persist across the lifetime of a document. It's created prior to the document and prior to the initiation of the resource load for the documents main resource. Today, when a cross-site xfer occurs the host is deleted and a new host is created that knows nothing of whats going on... so not surprisingly things are broken. Either state of the old host that gets deleted needs to be saved and restored into a new host that gets created... or the old host should not get deleted and instead get transferred along as well. I chose the latter because there's some state that can't be saved/restored so easily and moving the whole object is less tedious. BUG=331270 Review URL: https://codereview.chromium.org/137883005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@248631 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/browser/appcache/appcache_backend_impl.cc32
-rw-r--r--webkit/browser/appcache/appcache_backend_impl.h6
-rw-r--r--webkit/browser/appcache/appcache_host.cc14
-rw-r--r--webkit/browser/appcache/appcache_host.h4
-rw-r--r--webkit/browser/appcache/appcache_interceptor.cc21
-rw-r--r--webkit/browser/appcache/appcache_interceptor.h7
-rw-r--r--webkit/browser/appcache/appcache_request_handler.cc34
-rw-r--r--webkit/browser/appcache/appcache_request_handler.h8
8 files changed, 118 insertions, 8 deletions
diff --git a/webkit/browser/appcache/appcache_backend_impl.cc b/webkit/browser/appcache/appcache_backend_impl.cc
index fd8029d..17b0b0c 100644
--- a/webkit/browser/appcache/appcache_backend_impl.cc
+++ b/webkit/browser/appcache/appcache_backend_impl.cc
@@ -147,4 +147,36 @@ void AppCacheBackendImpl::GetResourceList(
host->GetResourceList(resource_infos);
}
+scoped_ptr<AppCacheHost> AppCacheBackendImpl::TransferHostOut(int host_id) {
+ HostMap::iterator found = hosts_.find(host_id);
+ if (found == hosts_.end()) {
+ NOTREACHED();
+ return scoped_ptr<AppCacheHost>();
+ }
+
+ AppCacheHost* transferree = found->second;
+
+ // Put a new empty host in its place.
+ found->second = new AppCacheHost(host_id, frontend_, service_);
+
+ // We give up ownership.
+ transferree->PrepareForTransfer();
+ return scoped_ptr<AppCacheHost>(transferree);
+}
+
+void AppCacheBackendImpl::TransferHostIn(
+ int new_host_id, scoped_ptr<AppCacheHost> host) {
+ HostMap::iterator found = hosts_.find(new_host_id);
+ if (found == hosts_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ delete found->second;
+
+ // We take onwership.
+ host->CompleteTransfer(new_host_id, frontend_);
+ found->second = host.release();
+}
+
} // namespace appcache
diff --git a/webkit/browser/appcache/appcache_backend_impl.h b/webkit/browser/appcache/appcache_backend_impl.h
index 2bdc574..0d1779f 100644
--- a/webkit/browser/appcache/appcache_backend_impl.h
+++ b/webkit/browser/appcache/appcache_backend_impl.h
@@ -57,6 +57,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheBackendImpl {
typedef base::hash_map<int, AppCacheHost*> HostMap;
const HostMap& hosts() { return hosts_; }
+ // Methods to support cross site navigations. Hosts are transferred
+ // from process to process accordingly, deparented from the old
+ // processes backend and reparented to the new.
+ scoped_ptr<AppCacheHost> TransferHostOut(int host_id);
+ void TransferHostIn(int new_host_id, scoped_ptr<AppCacheHost> host);
+
private:
AppCacheService* service_;
AppCacheFrontend* frontend_;
diff --git a/webkit/browser/appcache/appcache_host.cc b/webkit/browser/appcache/appcache_host.cc
index a8a86f8..598b100 100644
--- a/webkit/browser/appcache/appcache_host.cc
+++ b/webkit/browser/appcache/appcache_host.cc
@@ -489,6 +489,20 @@ void AppCacheHost::NotifyMainResourceBlocked(const GURL& manifest_url) {
blocked_manifest_url_ = manifest_url;
}
+void AppCacheHost::PrepareForTransfer() {
+ // This can only happen prior to the document having been loaded.
+ DCHECK(!associated_cache());
+ DCHECK(!is_selection_pending());
+ DCHECK(!group_being_updated_);
+ host_id_ = kNoHostId;
+ frontend_ = NULL;
+}
+
+void AppCacheHost::CompleteTransfer(int host_id, AppCacheFrontend* frontend) {
+ host_id_ = host_id;
+ frontend_ = frontend;
+}
+
void AppCacheHost::AssociateNoCache(const GURL& manifest_url) {
// manifest url can be empty.
AssociateCacheHelper(NULL, manifest_url);
diff --git a/webkit/browser/appcache/appcache_host.h b/webkit/browser/appcache/appcache_host.h
index 939d198..7bbb1f2 100644
--- a/webkit/browser/appcache/appcache_host.h
+++ b/webkit/browser/appcache/appcache_host.h
@@ -152,6 +152,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheHost
const GURL& first_party_url() const { return first_party_url_; }
+ // Methods to support cross site navigations.
+ void PrepareForTransfer();
+ void CompleteTransfer(int host_id, AppCacheFrontend* frontend);
+
private:
Status GetStatus();
void LoadSelectedCache(int64 cache_id);
diff --git a/webkit/browser/appcache/appcache_interceptor.cc b/webkit/browser/appcache/appcache_interceptor.cc
index 0fa8476..20d7668 100644
--- a/webkit/browser/appcache/appcache_interceptor.cc
+++ b/webkit/browser/appcache/appcache_interceptor.cc
@@ -62,6 +62,27 @@ void AppCacheInterceptor::GetExtraResponseInfo(net::URLRequest* request,
handler->GetExtraResponseInfo(cache_id, manifest_url);
}
+void AppCacheInterceptor::PrepareForCrossSiteTransfer(
+ net::URLRequest* request,
+ int old_process_id) {
+ AppCacheRequestHandler* handler = GetHandler(request);
+ if (!handler)
+ return;
+ handler->PrepareForCrossSiteTransfer(old_process_id);
+}
+
+void AppCacheInterceptor::CompleteCrossSiteTransfer(
+ net::URLRequest* request,
+ int new_process_id,
+ int new_host_id) {
+ AppCacheRequestHandler* handler = GetHandler(request);
+ if (!handler)
+ return;
+ DCHECK_NE(kNoHostId, new_host_id);
+ handler->CompleteCrossSiteTransfer(new_process_id,
+ new_host_id);
+}
+
AppCacheInterceptor::AppCacheInterceptor() {
net::URLRequest::Deprecated::RegisterRequestInterceptor(this);
}
diff --git a/webkit/browser/appcache/appcache_interceptor.h b/webkit/browser/appcache/appcache_interceptor.h
index b1db1c0..9ae223c 100644
--- a/webkit/browser/appcache/appcache_interceptor.h
+++ b/webkit/browser/appcache/appcache_interceptor.h
@@ -40,6 +40,13 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheInterceptor
int64* cache_id,
GURL* manifest_url);
+ // Methods to support cross site navigations.
+ static void PrepareForCrossSiteTransfer(net::URLRequest* request,
+ int old_process_id);
+ static void CompleteCrossSiteTransfer(net::URLRequest* request,
+ int new_process_id,
+ int new_host_id);
+
static AppCacheInterceptor* GetInstance();
protected:
diff --git a/webkit/browser/appcache/appcache_request_handler.cc b/webkit/browser/appcache/appcache_request_handler.cc
index 957cf20..102c184 100644
--- a/webkit/browser/appcache/appcache_request_handler.cc
+++ b/webkit/browser/appcache/appcache_request_handler.cc
@@ -7,6 +7,7 @@
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
#include "webkit/browser/appcache/appcache.h"
+#include "webkit/browser/appcache/appcache_backend_impl.h"
#include "webkit/browser/appcache/appcache_policy.h"
#include "webkit/browser/appcache/appcache_url_request_job.h"
@@ -34,14 +35,6 @@ AppCacheStorage* AppCacheRequestHandler::storage() const {
return host_->storage();
}
-void AppCacheRequestHandler::GetExtraResponseInfo(
- int64* cache_id, GURL* manifest_url) {
- if (job_.get() && job_->is_delivering_appcache_response()) {
- *cache_id = job_->cache_id();
- *manifest_url = job_->manifest_url();
- }
-}
-
AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadResource(
net::URLRequest* request, net::NetworkDelegate* network_delegate) {
maybe_load_resource_executed_ = true;
@@ -170,6 +163,31 @@ AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadFallbackForResponse(
return job_.get();
}
+void AppCacheRequestHandler::GetExtraResponseInfo(
+ int64* cache_id, GURL* manifest_url) {
+ if (job_.get() && job_->is_delivering_appcache_response()) {
+ *cache_id = job_->cache_id();
+ *manifest_url = job_->manifest_url();
+ }
+}
+
+void AppCacheRequestHandler::PrepareForCrossSiteTransfer(int old_process_id) {
+ if (!host_)
+ return;
+ AppCacheBackendImpl* backend = host_->service()->GetBackend(old_process_id);
+ host_for_cross_site_transfer_ = backend->TransferHostOut(host_->host_id());
+ DCHECK_EQ(host_, host_for_cross_site_transfer_.get());
+}
+
+void AppCacheRequestHandler::CompleteCrossSiteTransfer(
+ int new_process_id, int new_host_id) {
+ if (!host_for_cross_site_transfer_.get())
+ return;
+ DCHECK_EQ(host_, host_for_cross_site_transfer_.get());
+ AppCacheBackendImpl* backend = host_->service()->GetBackend(new_process_id);
+ backend->TransferHostIn(new_host_id, host_for_cross_site_transfer_.Pass());
+}
+
void AppCacheRequestHandler::OnDestructionImminent(AppCacheHost* host) {
storage()->CancelDelegateCallbacks(this);
host_ = NULL; // no need to RemoveObserver, the host is being deleted
diff --git a/webkit/browser/appcache/appcache_request_handler.h b/webkit/browser/appcache/appcache_request_handler.h
index 606d6cf..325313f 100644
--- a/webkit/browser/appcache/appcache_request_handler.h
+++ b/webkit/browser/appcache/appcache_request_handler.h
@@ -46,6 +46,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheRequestHandler
void GetExtraResponseInfo(int64* cache_id, GURL* manifest_url);
+ // Methods to support cross site navigations.
+ void PrepareForCrossSiteTransfer(int old_process_id);
+ void CompleteCrossSiteTransfer(int new_process_id, int new_host_id);
+
static bool IsMainResourceType(ResourceType::Type type) {
return ResourceType::IsFrame(type) ||
ResourceType::IsSharedWorker(type);
@@ -131,6 +135,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheRequestHandler
// The job we use to deliver a response.
scoped_refptr<AppCacheURLRequestJob> job_;
+ // During a cross site navigation, we transfer ownership the AppcacheHost
+ // from the old processes structures over to the new structures.
+ scoped_ptr<AppCacheHost> host_for_cross_site_transfer_;
+
friend class AppCacheRequestHandlerTest;
DISALLOW_COPY_AND_ASSIGN(AppCacheRequestHandler);
};