Index: webkit/browser/appcache/appcache_host.cc |
diff --git a/webkit/browser/appcache/appcache_host.cc b/webkit/browser/appcache/appcache_host.cc |
index efd8ce4f6a417b19d6a2f3108c4496dd44a2da85..c0a79b6b37c64010e0e0e2afbabf8c3a0a2ebf51 100644 |
--- a/webkit/browser/appcache/appcache_host.cc |
+++ b/webkit/browser/appcache/appcache_host.cc |
@@ -7,12 +7,14 @@ |
#include "base/logging.h" |
#include "base/strings/string_util.h" |
#include "base/strings/stringprintf.h" |
+#include "base/strings/utf_string_conversions.h" |
#include "net/url_request/url_request.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_request_handler.h" |
#include "webkit/browser/quota/quota_manager.h" |
+#include "webkit/browser/appcache/manifest_parser.h" |
namespace appcache { |
@@ -65,6 +67,8 @@ AppCacheHost::~AppCacheHost() { |
service_->storage()->CancelDelegateCallbacks(this); |
if (service()->quota_manager_proxy() && !origin_in_use_.is_empty()) |
service()->quota_manager_proxy()->NotifyOriginNoLongerInUse(origin_in_use_); |
+ if (controller_group_) |
+ controller_group_->RemoveUpdateObserver(this); |
} |
void AppCacheHost::AddObserver(Observer* observer) { |
@@ -83,6 +87,11 @@ void AppCacheHost::SelectCache(const GURL& document_url, |
pending_get_status_callback_.is_null() && |
!is_selection_pending()); |
+ // Note: extra logic to release this cache in case an exe handler |
+ // generated a redirect to a resource outside of the scope of this cache. |
+ scoped_refptr<AppCache> main_cache_releaser = main_resource_cache_; |
+ main_resource_cache_ = NULL; |
+ |
origin_in_use_ = document_url.GetOrigin(); |
if (service()->quota_manager_proxy() && !origin_in_use_.is_empty()) |
service()->quota_manager_proxy()->NotifyOriginInUse(origin_in_use_); |
@@ -103,6 +112,16 @@ void AppCacheHost::SelectCache(const GURL& document_url, |
return; |
} |
+ // Hackery for navcontroller semantics where the controller gets a crack |
+ // and any and all subresource requests <period> for any documents in its |
+ // controlled namespace. We force the containing cache to be associated. |
+ if (main_cache_releaser && |
+ main_cache_releaser->owning_group()->IsFakeNavControllerGroup() && |
+ main_cache_releaser->FindInterceptNamespace(document_url)) { |
+ LoadSelectedCache(main_cache_releaser->cache_id()); |
+ return; |
+ } |
+ |
if (!manifest_url.is_empty() && |
(manifest_url.GetOrigin() == document_url.GetOrigin())) { |
DCHECK(!first_party_url_.is_empty()); |
@@ -203,6 +222,58 @@ void AppCacheHost::StartUpdateWithCallback(const StartUpdateCallback& callback, |
DoPendingStartUpdate(); |
} |
+static void CreateControllerManifest(const GURL& manifest_url, |
+ const string16& pattern, |
+ const GURL& script_url, |
+ Manifest* manifest) { |
+ LOG(ERROR) << "CreateControllerManifest(" << manifest_url << ", " << pattern << ", " << script_url << ")"; |
+ // right now we only support prefix-like patterns |
+ std::string pattern_utf8 = UTF16ToUTF8(pattern); |
+ DCHECK(*pattern_utf8.rbegin() == '*') << "Only prefix patterns supported " << pattern_utf8; |
+ base::StringPiece prefix_pattern(pattern_utf8.c_str(), pattern_utf8.length() - 1); |
+ |
+ GURL namespace_url = manifest_url; // .Resolve(pattern); |
+ manifest->intercept_namespaces.push_back( |
+ Namespace(INTERCEPT_NAMESPACE, namespace_url, |
+ script_url, true, true)); |
+ LOG(ERROR) << " Created with namespace = " << namespace_url; |
+} |
+ |
+void AppCacheHost::RegisterController(const GURL& document_url, |
+ const string16& pattern, |
+ const GURL& script_url) { |
+ LOG(ERROR) << "Browser process got registerController(" << pattern << ", " << script_url << ")"; |
+ |
+ if (!controller_pattern_.empty()) { |
+ // You should be able to register any number of controllers at |
+ // different prefixes, but we're not setup to do that. |
+ LOG(ERROR) << "Trying to register pattern '" << pattern << "' with '" << script_url << "' but '" << controller_pattern_ << " has already been registered with '"<< controller_script_url_ << "'"; |
+ return; |
+ } |
+ |
+ controller_pattern_ = pattern; |
+ controller_script_url_ = script_url; |
+ controller_manifest_url_ = document_url.Resolve(pattern); |
+ controller_group_ = NULL; |
+ controller_cache_ = NULL; |
+ service_->storage()->LoadOrCreateGroup(controller_manifest_url_, this); |
+} |
+ |
+void AppCacheHost::UnregisterController(const GURL& document_url, |
+ const string16& pattern) { |
+ // Clear out old state so register can be called again from the containing page. |
+ if (controller_group_) |
+ controller_group_->RemoveUpdateObserver(this); |
+ controller_pattern_ = string16(); |
+ controller_script_url_ = GURL(); |
+ controller_manifest_url_ = GURL(); |
+ controller_group_ = NULL; |
+ controller_cache_ = NULL; |
+ |
+ // Delete the the 'controller cache' to unregister. |
+ service_->DeleteAppCacheGroup(document_url.Resolve(pattern), net::CompletionCallback()); |
+} |
+ |
void AppCacheHost::DoPendingStartUpdate() { |
DCHECK_EQ(false, pending_start_update_callback_.is_null()); |
@@ -334,11 +405,47 @@ void AppCacheHost::LoadOrCreateGroup(const GURL& manifest_url) { |
void AppCacheHost::OnGroupLoaded(AppCacheGroup* group, |
const GURL& manifest_url) { |
+ // special case |
+ if (manifest_url == controller_manifest_url_) { |
+ OnControllerGroupLoaded(group); |
+ return; |
+ } |
+ |
DCHECK(manifest_url == pending_selected_manifest_url_); |
pending_selected_manifest_url_ = GURL(); |
FinishCacheSelection(NULL, group); |
} |
+void AppCacheHost::OnControllerGroupLoaded(AppCacheGroup* group) { |
+ DCHECK(group); |
+ controller_group_ = group; // hang onto it to keep it alive |
+ if (group->HasCache()) { |
+ // We already have a controller camping on this pattern. |
+ // TODO: Need to see if it's exe handler url matches controller_script_url_, |
+ // and to update/recreate if it doesn't match, for now assume it matches |
+ // and just use it. |
+ controller_cache_ = group->newest_complete_cache(); |
+ frontend_->OnControllerReady(host_id_); |
+ return; |
+ } |
+ |
+ appcache::Manifest manifest; |
+ CreateControllerManifest(controller_manifest_url_, |
+ controller_pattern_, |
+ controller_script_url_, |
+ &manifest); |
+ // Nothing exists yet, need to run the update algo for the first time. |
+ group->AddUpdateObserver(this); |
+ group->StartUpdateWithFakeManifest(&manifest); |
+} |
+ |
+void AppCacheHost::OnControllerUpdateComplete(AppCacheGroup* group) { |
+ if (group->HasCache()) |
+ controller_cache_ = group->newest_complete_cache(); |
+ DCHECK(controller_cache_); |
+ frontend_->OnControllerReady(host_id_); |
+} |
+ |
void AppCacheHost::LoadSelectedCache(int64 cache_id) { |
DCHECK(cache_id != kNoCacheId); |
pending_selected_cache_id_ = cache_id; |
@@ -425,9 +532,15 @@ void AppCacheHost::ObserveGroupBeingUpdated(AppCacheGroup* group) { |
} |
void AppCacheHost::OnUpdateComplete(AppCacheGroup* group) { |
- DCHECK_EQ(group, group_being_updated_); |
group->RemoveUpdateObserver(this); |
+ if (group == controller_group_) { |
+ OnControllerUpdateComplete(group); |
+ return; |
+ } |
+ |
+ DCHECK_EQ(group, group_being_updated_); |
+ |
// Add a reference to the newest complete cache. |
SetSwappableCache(group); |