Index: content/browser/in_process_webkit/dom_storage_namespace.cc |
diff --git a/content/browser/in_process_webkit/dom_storage_namespace.cc b/content/browser/in_process_webkit/dom_storage_namespace.cc |
index 508786f1aaf58d7d8ba23b01793775028de8a052..d004f78d476925283c8ce31dd90ba156f62f44f0 100644 |
--- a/content/browser/in_process_webkit/dom_storage_namespace.cc |
+++ b/content/browser/in_process_webkit/dom_storage_namespace.cc |
@@ -5,9 +5,11 @@ |
#include "content/browser/in_process_webkit/dom_storage_namespace.h" |
#include "base/file_path.h" |
+#include "content/browser/content_browser_client.h" |
#include "content/browser/in_process_webkit/dom_storage_area.h" |
#include "content/browser/in_process_webkit/dom_storage_context.h" |
#include "content/browser/in_process_webkit/dom_storage_message_filter.h" |
+#include "content/common/content_client.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageArea.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageNamespace.h" |
#include "webkit/glue/webkit_glue.h" |
@@ -16,6 +18,58 @@ using WebKit::WebStorageArea; |
using WebKit::WebStorageNamespace; |
using WebKit::WebString; |
+namespace { |
jochen (gone - plz use gerrit)
2011/07/29 08:01:06
why not make these two functions method of DOMStor
marja
2011/08/01 08:36:32
Done.
|
+ |
+void CreateStorageAreaInWebKitThread(DOMStorageNamespace* dom_storage_namespace, |
+ const string16& origin, |
+ bool allow_permanent_storage, |
+ DOMStorageNamespace::Delegate* delegate, |
+ IPC::Message* reply_msg) { |
+ // It's possible that the same origin has been requested by multiple |
+ // renderers. There can be multiple CreateStorageAreaInWebKitThread tasks in |
+ // the event queue and the WebKit thread will process them sequentally. Each |
+ // task needs to check if the storage area got created by a previous task. |
+ DOMStorageArea* storage_area = |
+ dom_storage_namespace->GetExistingStorageArea(origin); |
+ if (storage_area) { |
+ if (delegate) |
+ delegate->OnGotStorageArea(storage_area, reply_msg); |
+ return; |
+ } |
+ dom_storage_namespace->CreateStorageAreaInWebKitThread( |
+ origin, |
+ allow_permanent_storage, |
+ delegate, |
+ reply_msg); |
+} |
+ |
+void ReadContentSettingsOnIOThread( |
+ DOMStorageContext* dom_storage_context, |
+ const string16& origin, |
+ const string16& first_party_origin, |
+ DOMStorageNamespace* dom_storage_namespace, |
+ DOMStorageNamespace::Delegate* delegate, |
+ IPC::Message* reply_msg) { |
+ content::ContentBrowserClient* content_browser_client = |
+ content::GetContentClient()->browser(); |
+ bool allow_permanent_storage = |
+ content_browser_client->AllowPermanentStorage( |
+ GURL(origin), |
+ GURL(first_party_origin), |
+ dom_storage_context->GetResourceContext()); |
+ BrowserThread::PostTask(BrowserThread::WEBKIT, |
+ FROM_HERE, |
+ NewRunnableFunction( |
+ CreateStorageAreaInWebKitThread, |
+ dom_storage_namespace, |
+ origin, |
+ allow_permanent_storage, |
+ delegate, |
+ reply_msg)); |
+} |
+ |
+} // namespace |
+ |
/* static */ |
DOMStorageNamespace* DOMStorageNamespace::CreateLocalStorageNamespace( |
DOMStorageContext* dom_storage_context, const FilePath& data_dir_path) { |
@@ -41,6 +95,15 @@ DOMStorageNamespace::DOMStorageNamespace(DOMStorageContext* dom_storage_context, |
id_(id), |
data_dir_path_(data_dir_path), |
dom_storage_type_(dom_storage_type) { |
+ if (dom_storage_type == DOM_STORAGE_LOCAL && !data_dir_path.isEmpty()) { |
+ // This DOMStorageNamespace represents permanent storage; create a sibling |
+ // namespace that represents the corresponding session-only storage. |
+ session_only_local_storage_.reset( |
+ new DOMStorageNamespace(dom_storage_context, |
+ id, |
+ WebString(), |
+ dom_storage_type)); |
+ } |
DCHECK(dom_storage_context_); |
} |
@@ -54,19 +117,36 @@ DOMStorageNamespace::~DOMStorageNamespace() { |
} |
} |
-DOMStorageArea* DOMStorageNamespace::GetStorageArea(const string16& origin) { |
+DOMStorageArea* DOMStorageNamespace::GetStorageArea(const string16& origin, |
+ Delegate* delegate, |
+ IPC::Message* reply_msg) { |
// We may have already created it for another dispatcher host. |
- OriginToStorageAreaMap::iterator iter = origin_to_storage_area_.find(origin); |
- if (iter != origin_to_storage_area_.end()) |
- return iter->second; |
+ DOMStorageArea* storage_area = GetExistingStorageArea(origin); |
+ if (storage_area) |
+ return storage_area; |
+ // Else, we need to create a new DOMStorageArea. |
- // We need to create a new one. |
- int64 id = dom_storage_context_->AllocateStorageAreaId(); |
- DCHECK(!dom_storage_context_->GetStorageArea(id)); |
- DOMStorageArea* storage_area = new DOMStorageArea(origin, id, this); |
- origin_to_storage_area_[origin] = storage_area; |
- dom_storage_context_->RegisterStorageArea(storage_area); |
- return storage_area; |
+ if (session_only_local_storage_.get()) { |
+ // We have a session-only sibling DOMStorageNamespace, so we need to check |
+ // whether to create it in this or in the sibling. We're now in the WebKit |
+ // thread, but the content settings need to be accessed in the IO thread. |
+ BrowserThread::PostTask(BrowserThread::IO, |
+ FROM_HERE, |
+ NewRunnableFunction( |
+ ReadContentSettingsOnIOThread, |
+ dom_storage_context_, |
+ origin, |
+ // FIXME(marja): get the first-party url |
+ origin, |
+ this, |
+ delegate, |
+ reply_msg)); |
+ return NULL; |
+ } |
+ else { |
+ // No sibling; handle creation here. |
+ return CreateStorageAreaInWebKitThread(origin, true, NULL, NULL); |
+ } |
} |
DOMStorageNamespace* DOMStorageNamespace::Copy(int64 id) { |
@@ -107,3 +187,46 @@ void DOMStorageNamespace::CreateWebStorageNamespaceIfNecessary() { |
WebStorageNamespace::m_sessionStorageQuota)); |
} |
} |
+ |
+DOMStorageArea* DOMStorageNamespace::GetExistingStorageArea( |
+ const string16& origin) { |
+ OriginToStorageAreaMap::iterator iter = origin_to_storage_area_.find(origin); |
+ if (iter != origin_to_storage_area_.end()) |
+ return iter->second; |
+ |
+ // Our our session-only sibling might have it. (This is independent of what |
+ // the content settings say; it might be that the settings were changed after |
+ // the DOMStorageArea was created.) |
+ if (session_only_local_storage_.get()) { |
+ iter = session_only_local_storage_->origin_to_storage_area_.find(origin); |
+ if (iter != session_only_local_storage_->origin_to_storage_area_.end()) |
+ return iter->second; |
+ } |
+ return NULL; |
+} |
+ |
+DOMStorageArea* DOMStorageNamespace::CreateStorageAreaInWebKitThread( |
+ const string16& origin, |
+ bool allow_permanent_storage, |
+ Delegate* delegate, |
+ IPC::Message* reply_msg) { |
+ DOMStorageArea* storage_area = NULL; |
+ if (session_only_local_storage_.get() && |
+ !allow_permanent_storage) { |
+ // For that origin, only session-only data is allowed, and we have a |
+ // sibling namespace taking care of it. This will finish immediately, |
+ // since the sibling won't check again whether the permanent storage is |
+ // allowed. |
+ storage_area = |
+ session_only_local_storage_->GetStorageArea(origin, NULL, NULL); |
+ } else { |
+ int64 id = dom_storage_context_->AllocateStorageAreaId(); |
+ DCHECK(!dom_storage_context_->GetStorageArea(id)); |
+ storage_area = new DOMStorageArea(origin, id, this); |
+ origin_to_storage_area_[origin] = storage_area; |
+ dom_storage_context_->RegisterStorageArea(storage_area); |
+ } |
+ if (delegate) |
+ delegate->OnGotStorageArea(storage_area, reply_msg); |
+ return storage_area; |
+} |