| 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 {
|
| +
|
| +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;
|
| +}
|
|
|