diff options
author | jorlow@chromium.org <jorlow@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-08 03:54:49 +0000 |
---|---|---|
committer | jorlow@chromium.org <jorlow@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-08 03:54:49 +0000 |
commit | c7fd0cbdbd381035ecd95d164a59d874b41d9339 (patch) | |
tree | 9956e58e7eb8b9098301cca6f1330ed5a3a1a348 /chrome/browser/in_process_webkit | |
parent | b4599a15c90a853930187cc751c951beb819c02d (diff) | |
download | chromium_src-c7fd0cbdbd381035ecd95d164a59d874b41d9339.zip chromium_src-c7fd0cbdbd381035ecd95d164a59d874b41d9339.tar.gz chromium_src-c7fd0cbdbd381035ecd95d164a59d874b41d9339.tar.bz2 |
Refactor DOM storage to be more object oriented. All the DOMStorageDispatcher hosts (which are each owned by one ResourceMessageFilter) for the same profile share a WebKit context, and each one of those contexts owns a DOMStorageContext. The DOMStorageContext owns storage namespace objects which own storage area objects which wrap their WebKit counterparts.
Not only is this cleaner code wise and more efficient (we're not duplicating WebStorageNamespaces and Areas for each DOMStorageDispatcherHost) but this is necessary for events and locking.
TEST=none
BUG=none
Review URL: http://codereview.chromium.org/192003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25609 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/in_process_webkit')
12 files changed, 511 insertions, 150 deletions
diff --git a/chrome/browser/in_process_webkit/dom_storage_context.cc b/chrome/browser/in_process_webkit/dom_storage_context.cc new file mode 100644 index 0000000..b22d976 --- /dev/null +++ b/chrome/browser/in_process_webkit/dom_storage_context.cc @@ -0,0 +1,84 @@ +// 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 "chrome/browser/in_process_webkit/dom_storage_context.h" + +#include "base/file_path.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/in_process_webkit/storage_area.h" +#include "chrome/browser/in_process_webkit/storage_namespace.h" +#include "chrome/browser/in_process_webkit/webkit_context.h" + +DOMStorageContext::DOMStorageContext(WebKitContext* webkit_context) + : last_storage_area_id_(kFirstStorageAreaId), + last_storage_namespace_id_(kFirstStorageNamespaceId), + webkit_context_(webkit_context) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); +} + +DOMStorageContext::~DOMStorageContext() { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); + // The storage namespace destructor unregisters the storage namespace, so + // our iterator becomes invalid. Thus we just keep deleting the first item + // until there are none left. + while (!storage_namespace_map_.empty()) + delete storage_namespace_map_.begin()->second; +} + +StorageNamespace* DOMStorageContext::LocalStorage() { + StorageNamespace* storage_namespace = GetStorageNamespace( + kLocalStorageNamespaceId); + if (storage_namespace) + return storage_namespace; + + FilePath data_path = webkit_context_->data_path(); + FilePath dir_path; + if (!data_path.empty()) + dir_path = data_path.AppendASCII("localStorage"); + return StorageNamespace::CreateLocalStorageNamespace(this, dir_path); +} + +StorageNamespace* DOMStorageContext::NewSessionStorage() { + return StorageNamespace::CreateSessionStorageNamespace(this); +} + +void DOMStorageContext::RegisterStorageArea(StorageArea* storage_area) { + int64 id = storage_area->id(); + DCHECK(!GetStorageArea(id)); + storage_area_map_[id] = storage_area; +} + +void DOMStorageContext::UnregisterStorageArea(StorageArea* storage_area) { + int64 id = storage_area->id(); + DCHECK(GetStorageArea(id)); + storage_area_map_.erase(id); +} + +StorageArea* DOMStorageContext::GetStorageArea(int64 id) { + StorageAreaMap::iterator iter = storage_area_map_.find(id); + if (iter == storage_area_map_.end()) + return NULL; + return iter->second; +} + +void DOMStorageContext::RegisterStorageNamespace( + StorageNamespace* storage_namespace) { + int64 id = storage_namespace->id(); + DCHECK(!GetStorageNamespace(id)); + storage_namespace_map_[id] = storage_namespace; +} + +void DOMStorageContext::UnregisterStorageNamespace( + StorageNamespace* storage_namespace) { + int64 id = storage_namespace->id(); + DCHECK(GetStorageNamespace(id)); + storage_namespace_map_.erase(id); +} + +StorageNamespace* DOMStorageContext::GetStorageNamespace(int64 id) { + StorageNamespaceMap::iterator iter = storage_namespace_map_.find(id); + if (iter == storage_namespace_map_.end()) + return NULL; + return iter->second; +} diff --git a/chrome/browser/in_process_webkit/dom_storage_context.h b/chrome/browser/in_process_webkit/dom_storage_context.h new file mode 100644 index 0000000..ba26ac2 --- /dev/null +++ b/chrome/browser/in_process_webkit/dom_storage_context.h @@ -0,0 +1,72 @@ +// 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 CHROME_BROWSER_IN_PROCESS_WEBKIT_DOM_STORAGE_CONTEXT_H_ +#define CHROME_BROWSER_IN_PROCESS_WEBKIT_DOM_STORAGE_CONTEXT_H_ + +#include "base/file_path.h" +#include "base/hash_tables.h" + +class StorageArea; +class StorageNamespace; +class WebKitContext; + +// This is owned by WebKitContext and is all the dom storage information that's +// shared by all the ResourceMessageFilter/DOMStorageDispatcherHosts that share +// the same profile. The specifics of responsibilities are fairly well +// documented here and in StorageNamespace and StorageArea. +class DOMStorageContext { + public: + explicit DOMStorageContext(WebKitContext* webkit_context); + ~DOMStorageContext(); + + // Get the local storage instance. The pointer is owned by this class. + StorageNamespace* LocalStorage(); + + // Get a new session storage namespace (but it's still owned by this class). + StorageNamespace* NewSessionStorage(); + + // Allocate a new storage ___ id. + int64 AllocateStorageAreaId() { return ++last_storage_area_id_; } + int64 AllocateStorageNamespaceId() { return ++last_storage_namespace_id_; } + + // Various storage area methods. The storage area is owned by one of the + // namespaces that's owned by this class. + void RegisterStorageArea(StorageArea* storage_area); + void UnregisterStorageArea(StorageArea* storage_area); + StorageArea* GetStorageArea(int64 id); + + // Get a namespace from an id. What's returned is owned by this class. The + // caller of GetStorageNamespace must immediately register itself with the + // returned StorageNamespace. + void RegisterStorageNamespace(StorageNamespace* storage_namespace); + void UnregisterStorageNamespace(StorageNamespace* storage_namespace); + StorageNamespace* GetStorageNamespace(int64 id); + + // The special ID used for local storage. + static const int64 kLocalStorageNamespaceId = 0; + + private: + // The last used storage_area_id and storage_namespace_id's. + static const int64 kFirstStorageAreaId = 1; + int64 last_storage_area_id_; + static const int64 kFirstStorageNamespaceId = 1; + int64 last_storage_namespace_id_; + + // We're owned by this WebKit context. Used while instantiating LocalStorage. + WebKitContext* webkit_context_; + + // Maps ids to StorageAreas. We do NOT own these objects. StorageNamespace + // (which does own them) will notify us when we should remove the entries. + typedef base::hash_map<int64, StorageArea*> StorageAreaMap; + StorageAreaMap storage_area_map_; + + // Maps ids to StorageNamespaces. We own these objects. + typedef base::hash_map<int64, StorageNamespace*> StorageNamespaceMap; + StorageNamespaceMap storage_namespace_map_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(DOMStorageContext); +}; + +#endif // CHROME_BROWSER_IN_PROCESS_WEBKIT_DOM_STORAGE_CONTEXT_H_ diff --git a/chrome/browser/in_process_webkit/dom_storage_dispatcher_host.cc b/chrome/browser/in_process_webkit/dom_storage_dispatcher_host.cc index abded7c..bd1ba65 100644 --- a/chrome/browser/in_process_webkit/dom_storage_dispatcher_host.cc +++ b/chrome/browser/in_process_webkit/dom_storage_dispatcher_host.cc @@ -5,20 +5,12 @@ #include "chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h" #include "base/nullable_string16.h" -#include "base/stl_util-inl.h" #include "chrome/browser/chrome_thread.h" -#include "chrome/browser/in_process_webkit/webkit_context.h" +#include "chrome/browser/in_process_webkit/dom_storage_context.h" +#include "chrome/browser/in_process_webkit/storage_area.h" +#include "chrome/browser/in_process_webkit/storage_namespace.h" #include "chrome/browser/in_process_webkit/webkit_thread.h" #include "chrome/common/render_messages.h" -#include "webkit/api/public/WebKit.h" -#include "webkit/api/public/WebStorageArea.h" -#include "webkit/api/public/WebStorageNamespace.h" -#include "webkit/api/public/WebString.h" -#include "webkit/glue/webkit_glue.h" - -using WebKit::WebStorageArea; -using WebKit::WebStorageNamespace; -using WebKit::WebString; DOMStorageDispatcherHost::DOMStorageDispatcherHost( IPC::Message::Sender* message_sender, @@ -27,8 +19,6 @@ DOMStorageDispatcherHost::DOMStorageDispatcherHost( : webkit_context_(webkit_context), webkit_thread_(webkit_thread), message_sender_(message_sender), - last_storage_area_id_(0), - last_storage_namespace_id_(0), ever_used_(false), shutdown_(false) { DCHECK(webkit_context_.get()); @@ -38,14 +28,13 @@ DOMStorageDispatcherHost::DOMStorageDispatcherHost( DOMStorageDispatcherHost::~DOMStorageDispatcherHost() { DCHECK(shutdown_); - // TODO(jorlow): This sometimes fails on the bots. Why?? - //DCHECK(!ever_used_ || ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); } void DOMStorageDispatcherHost::Shutdown() { if (ChromeThread::CurrentlyOn(ChromeThread::IO)) { message_sender_ = NULL; if (!ever_used_) { + // No need to (possibly) spin up the WebKit thread for a no-op. shutdown_ = true; return; } @@ -60,12 +49,10 @@ void DOMStorageDispatcherHost::Shutdown() { DCHECK(ever_used_); DCHECK(!message_sender_); DCHECK(!shutdown_); - - STLDeleteContainerPairSecondPointers(storage_area_map_.begin(), - storage_area_map_.end()); - STLDeleteContainerPairSecondPointers(storage_namespace_map_.begin(), - storage_namespace_map_.end()); shutdown_ = true; + + // TODO(jorlow): If we have any locks, release them here. (Must be on the + // WebKit thread.) } bool DOMStorageDispatcherHost::OnMessageReceived(const IPC::Message& message, @@ -127,16 +114,13 @@ void DOMStorageDispatcherHost::OnNamespaceId(bool is_local_storage, } DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); - WebStorageNamespace* new_namespace; - if (is_local_storage) { - new_namespace = WebStorageNamespace::createLocalStorageNamespace( - GetLocalStoragePath()); - } else { - new_namespace = WebStorageNamespace::createSessionStorageNamespace(); - } - int64 new_namespace_id = AddStorageNamespace(new_namespace); + StorageNamespace* new_namespace; + if (is_local_storage) + new_namespace = Context()->LocalStorage(); + else + new_namespace = Context()->NewSessionStorage(); ViewHostMsg_DOMStorageNamespaceId::WriteReplyParams(reply_msg, - new_namespace_id); + new_namespace->id()); Send(reply_msg); } @@ -152,12 +136,12 @@ void DOMStorageDispatcherHost::OnCloneNamespaceId(int64 namespace_id, } DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); - WebStorageNamespace* existing_namespace = GetStorageNamespace(namespace_id); + StorageNamespace* existing_namespace = + Context()->GetStorageNamespace(namespace_id); CHECK(existing_namespace); // TODO(jorlow): Do better than this. - WebStorageNamespace* new_namespace = existing_namespace->copy(); - int64 new_namespace_id = AddStorageNamespace(new_namespace); + StorageNamespace* new_namespace = existing_namespace->Copy(); ViewHostMsg_DOMStorageCloneNamespaceId::WriteReplyParams(reply_msg, - new_namespace_id); + new_namespace->id()); Send(reply_msg); } @@ -171,7 +155,11 @@ void DOMStorageDispatcherHost::OnDerefNamespaceId(int64 namespace_id) { } DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); - // TODO(jorlow): We need to track resources so we can free them. + StorageNamespace* storage_namespace = + Context()->GetStorageNamespace(namespace_id); + CHECK(storage_namespace); // TODO(jorlow): Do better than this. + // TODO(jorlow): Track resources here so we can free them (even beyond just + // when the renderer process dies). } void DOMStorageDispatcherHost::OnStorageAreaId(int64 namespace_id, @@ -187,12 +175,12 @@ void DOMStorageDispatcherHost::OnStorageAreaId(int64 namespace_id, } DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); - WebStorageNamespace* storage_namespace = GetStorageNamespace(namespace_id); + StorageNamespace* storage_namespace = + Context()->GetStorageNamespace(namespace_id); CHECK(storage_namespace); // TODO(jorlow): Do better than this. - WebStorageArea* storage_area = storage_namespace->createStorageArea(origin); - int64 storage_area_id = AddStorageArea(storage_area); + StorageArea* storage_area = storage_namespace->GetStorageArea(origin); ViewHostMsg_DOMStorageCloneNamespaceId::WriteReplyParams(reply_msg, - storage_area_id); + storage_area->id()); Send(reply_msg); } @@ -206,12 +194,11 @@ void DOMStorageDispatcherHost::OnLock(int64 storage_area_id, return; } - DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); - bool invalidate_cache; - size_t bytes_left_in_quota; - WebStorageArea* storage_area = GetStorageArea(storage_area_id); + StorageArea* storage_area = Context()->GetStorageArea(storage_area_id); CHECK(storage_area); // TODO(jorlow): Do better than this. - storage_area->lock(invalidate_cache, bytes_left_in_quota); + // TODO(jorlow): Implement locking, quotas, etc... + bool invalidate_cache = true; + size_t bytes_left_in_quota = 9999999; ViewHostMsg_DOMStorageLock::WriteReplyParams(reply_msg, invalidate_cache, bytes_left_in_quota); Send(reply_msg); @@ -227,9 +214,9 @@ void DOMStorageDispatcherHost::OnUnlock(int64 storage_area_id) { } DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); - WebStorageArea* storage_area = GetStorageArea(storage_area_id); + StorageArea* storage_area = Context()->GetStorageArea(storage_area_id); CHECK(storage_area); // TODO(jorlow): Do better than this. - storage_area->unlock(); + // TODO(jorlow): Do something. } void DOMStorageDispatcherHost::OnLength(int64 storage_area_id, @@ -243,9 +230,9 @@ void DOMStorageDispatcherHost::OnLength(int64 storage_area_id, } DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); - WebStorageArea* storage_area = GetStorageArea(storage_area_id); + StorageArea* storage_area = Context()->GetStorageArea(storage_area_id); CHECK(storage_area); // TODO(jorlow): Do better than this. - unsigned length = storage_area->length(); + unsigned length = storage_area->Length(); ViewHostMsg_DOMStorageLength::WriteReplyParams(reply_msg, length); Send(reply_msg); } @@ -261,9 +248,9 @@ void DOMStorageDispatcherHost::OnKey(int64 storage_area_id, unsigned index, } DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); - WebStorageArea* storage_area = GetStorageArea(storage_area_id); + StorageArea* storage_area = Context()->GetStorageArea(storage_area_id); CHECK(storage_area); // TODO(jorlow): Do better than this. - const NullableString16& key = storage_area->key(index); + const NullableString16& key = storage_area->Key(index); ViewHostMsg_DOMStorageKey::WriteReplyParams(reply_msg, key); Send(reply_msg); } @@ -281,9 +268,9 @@ void DOMStorageDispatcherHost::OnGetItem(int64 storage_area_id, } DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); - WebStorageArea* storage_area = GetStorageArea(storage_area_id); + StorageArea* storage_area = Context()->GetStorageArea(storage_area_id); CHECK(storage_area); // TODO(jorlow): Do better than this. - const NullableString16& value = storage_area->getItem(key); + const NullableString16& value = storage_area->GetItem(key); ViewHostMsg_DOMStorageGetItem::WriteReplyParams(reply_msg, value); Send(reply_msg); } @@ -301,9 +288,9 @@ void DOMStorageDispatcherHost::OnSetItem(int64 storage_area_id, DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); bool quota_exception = false; - WebStorageArea* storage_area = GetStorageArea(storage_area_id); + StorageArea* storage_area = Context()->GetStorageArea(storage_area_id); CHECK(storage_area); // TODO(jorlow): Do better than this. - storage_area->setItem(key, value, quota_exception); + storage_area->SetItem(key, value, "a_exception); DCHECK(!quota_exception); // This is tracked by the renderer. } @@ -318,9 +305,9 @@ void DOMStorageDispatcherHost::OnRemoveItem(int64 storage_area_id, } DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); - WebStorageArea* storage_area = GetStorageArea(storage_area_id); + StorageArea* storage_area = Context()->GetStorageArea(storage_area_id); CHECK(storage_area); // TODO(jorlow): Do better than this. - storage_area->removeItem(key); + storage_area->RemoveItem(key); } void DOMStorageDispatcherHost::OnClear(int64 storage_area_id, @@ -335,51 +322,11 @@ void DOMStorageDispatcherHost::OnClear(int64 storage_area_id, DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); // TODO(jorlow): Return the total quota for this domain. - size_t bytes_left_in_quota = 0; - WebStorageArea* storage_area = GetStorageArea(storage_area_id); + size_t bytes_left_in_quota = 9999999; + StorageArea* storage_area = Context()->GetStorageArea(storage_area_id); CHECK(storage_area); // TODO(jorlow): Do better than this. - storage_area->clear(); + storage_area->Clear(); ViewHostMsg_DOMStorageClear::WriteReplyParams(reply_msg, bytes_left_in_quota); Send(reply_msg); } - -WebStorageArea* DOMStorageDispatcherHost::GetStorageArea(int64 id) { - StorageAreaMap::iterator iterator = storage_area_map_.find(id); - if (iterator == storage_area_map_.end()) - return NULL; - return iterator->second; -} - -WebStorageNamespace* DOMStorageDispatcherHost::GetStorageNamespace(int64 id) { - StorageNamespaceMap::iterator iterator = storage_namespace_map_.find(id); - if (iterator == storage_namespace_map_.end()) - return NULL; - return iterator->second; -} - -int64 DOMStorageDispatcherHost::AddStorageArea( - WebStorageArea* new_storage_area) { - // Create a new ID and insert it into our map. - int64 new_storage_area_id = ++last_storage_area_id_; - DCHECK(!GetStorageArea(new_storage_area_id)); - storage_area_map_[new_storage_area_id] = new_storage_area; - return new_storage_area_id; -} - -int64 DOMStorageDispatcherHost::AddStorageNamespace( - WebStorageNamespace* new_namespace) { - // Create a new ID and insert it into our map. - int64 new_namespace_id = ++last_storage_namespace_id_; - DCHECK(!GetStorageNamespace(new_namespace_id)); - storage_namespace_map_[new_namespace_id] = new_namespace; - return new_namespace_id; -} - -WebString DOMStorageDispatcherHost::GetLocalStoragePath() { - const FilePath& path = webkit_context_->data_path(); - if (path.empty()) - return WebString(); - FilePath::StringType path_string = path.AppendASCII("localStorage").value(); - return webkit_glue::FilePathStringToWebString(path_string); -} diff --git a/chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h b/chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h index c9a6039..72b061f 100644 --- a/chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h +++ b/chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h @@ -7,18 +7,13 @@ #include "base/hash_tables.h" #include "base/ref_counted.h" -#include "base/scoped_ptr.h" +#include "chrome/browser/in_process_webkit/storage_area.h" +#include "chrome/browser/in_process_webkit/webkit_context.h" #include "ipc/ipc_message.h" -class WebKitContext; +class DOMStorageContext; class WebKitThread; -namespace WebKit { -class WebStorageArea; -class WebStorageNamespace; -class WebString; -} - // This class handles the logistics of DOM Storage within the browser process. // It mostly ferries information between IPCs and the WebKit implementations, // but it also handles some special cases like when renderer processes die. @@ -58,19 +53,11 @@ class DOMStorageDispatcherHost : void OnRemoveItem(int64 storage_area_id, const string16& key); void OnClear(int64 storage_area_id, IPC::Message* reply_msg); - // Get a WebStorageNamespace or WebStorageArea based from its ID. Only call - // on the WebKit thread. - WebKit::WebStorageArea* GetStorageArea(int64 id); - WebKit::WebStorageNamespace* GetStorageNamespace(int64 id); - - // Add a WebStorageNamespace or WebStorageArea and get a new unique ID for - // it. Only call on the WebKit thread. - int64 AddStorageArea(WebKit::WebStorageArea* new_storage_area); - int64 AddStorageNamespace(WebKit::WebStorageNamespace* new_namespace); - - // Get the path to the LocalStorage directory. Calculate it if we haven't - // already. Only call on the WebKit thread. - WebKit::WebString GetLocalStoragePath(); + // A shortcut for accessing our context. + DOMStorageContext* Context() { + DCHECK(!shutdown_); + return webkit_context_->GetDOMStorageContext(); + } // Data shared between renderer processes with the same profile. scoped_refptr<WebKitContext> webkit_context_; @@ -81,22 +68,6 @@ class DOMStorageDispatcherHost : // Only set on the IO thread. IPC::Message::Sender* message_sender_; - // The last used storage_area_id and storage_namespace_id's. Only use on the - // WebKit thread. - int64 last_storage_area_id_; - int64 last_storage_namespace_id_; - - // Used to maintain a mapping between storage_area_id's used in IPC messages - // and the actual WebStorageArea instances. Only use on the WebKit thread. - typedef base::hash_map<int64, WebKit::WebStorageArea*> StorageAreaMap; - StorageAreaMap storage_area_map_; - - // Mapping between storage_namespace_id's used in IPC messages and the - // WebStorageNamespace instances. Only use on the WebKit thread. - typedef base::hash_map<int64, WebKit::WebStorageNamespace*> - StorageNamespaceMap; - StorageNamespaceMap storage_namespace_map_; - // Has this dispatcher ever handled a message. If not, then we can skip // the entire shutdown procedure. This is only set to true on the IO thread // and must be true if we're reading it on the WebKit thread. diff --git a/chrome/browser/in_process_webkit/storage_area.cc b/chrome/browser/in_process_webkit/storage_area.cc new file mode 100644 index 0000000..11369c5 --- /dev/null +++ b/chrome/browser/in_process_webkit/storage_area.cc @@ -0,0 +1,46 @@ +// 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 "chrome/browser/in_process_webkit/storage_area.h" + +#include "chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h" +#include "webkit/api/public/WebStorageArea.h" +#include "webkit/api/public/WebString.h" + +using WebKit::WebStorageArea; + +StorageArea::StorageArea(const string16& origin, WebStorageArea* storage_area, + int64 id) + : origin_(origin), + storage_area_(storage_area), + id_(id) { +} + +StorageArea::~StorageArea() { +} + +unsigned StorageArea::Length() { + return storage_area_->length(); +} + +NullableString16 StorageArea::Key(unsigned index) { + return storage_area_->key(index); +} + +NullableString16 StorageArea::GetItem(const string16& key) { + return storage_area_->getItem(key); +} + +void StorageArea::SetItem(const string16& key, const string16& value, + bool* quota_exception) { + storage_area_->setItem(key, value, *quota_exception); +} + +void StorageArea::RemoveItem(const string16& key) { + storage_area_->removeItem(key); +} + +void StorageArea::Clear() { + storage_area_->clear(); +} diff --git a/chrome/browser/in_process_webkit/storage_area.h b/chrome/browser/in_process_webkit/storage_area.h new file mode 100644 index 0000000..d6c6615 --- /dev/null +++ b/chrome/browser/in_process_webkit/storage_area.h @@ -0,0 +1,59 @@ +// 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 CHROME_BROWSER_IN_PROCESS_WEBKIT_STORAGE_AREA_H_ +#define CHROME_BROWSER_IN_PROCESS_WEBKIT_STORAGE_AREA_H_ + +#include "base/hash_tables.h" +#include "base/nullable_string16.h" + +namespace WebKit { +class WebStorageArea; +} + +// Only use on the WebKit thread. StorageNamespace manages our registration +// with DOMStorageContext. +class StorageArea { + public: + StorageArea(const string16& origin, WebKit::WebStorageArea* storage_area, + int64 id); + ~StorageArea(); + + unsigned Length(); + NullableString16 Key(unsigned index); + NullableString16 GetItem(const string16& key); + void SetItem(const string16& key, const string16& value, + bool* quota_xception); + void RemoveItem(const string16& key); + void Clear(); + + int64 id() const { return id_; } + + private: + // The origin this storage area represents. + string16 origin_; + + // The storage area we wrap. + WebKit::WebStorageArea* storage_area_; + + // Our storage area id. Unique to our parent WebKitContext. + int64 id_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(StorageArea); +}; + +#if defined(COMPILER_GCC) +namespace __gnu_cxx { + +template<> +struct hash<StorageArea*> { + std::size_t operator()(StorageArea* const& p) const { + return reinterpret_cast<std::size_t>(p); + } +}; + +} // namespace __gnu_cxx +#endif + +#endif // CHROME_BROWSER_IN_PROCESS_WEBKIT_STORAGE_AREA_H_ diff --git a/chrome/browser/in_process_webkit/storage_namespace.cc b/chrome/browser/in_process_webkit/storage_namespace.cc new file mode 100644 index 0000000..25548c3 --- /dev/null +++ b/chrome/browser/in_process_webkit/storage_namespace.cc @@ -0,0 +1,95 @@ +// 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 "chrome/browser/in_process_webkit/storage_namespace.h" + +#include "base/file_path.h" +#include "chrome/browser/in_process_webkit/dom_storage_context.h" +#include "chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h" +#include "chrome/browser/in_process_webkit/storage_area.h" +#include "webkit/api/public/WebStorageArea.h" +#include "webkit/api/public/WebStorageNamespace.h" +#include "webkit/api/public/WebString.h" +#include "webkit/glue/webkit_glue.h" + +using WebKit::WebStorageArea; +using WebKit::WebStorageNamespace; +using WebKit::WebString; + +/* static */ +StorageNamespace* StorageNamespace::CreateLocalStorageNamespace( + DOMStorageContext* dom_storage_context, const FilePath& dir_path) { + int64 id = dom_storage_context->kLocalStorageNamespaceId; + DCHECK(!dom_storage_context->GetStorageNamespace(id)); + WebString path = webkit_glue::FilePathToWebString(dir_path); + WebStorageNamespace* web_storage_namespace = + WebStorageNamespace::createLocalStorageNamespace(path); + return new StorageNamespace(dom_storage_context, web_storage_namespace, id, + true); +} + +/* static */ +StorageNamespace* StorageNamespace::CreateSessionStorageNamespace( + DOMStorageContext* dom_storage_context) { + int64 id = dom_storage_context->AllocateStorageNamespaceId(); + DCHECK(!dom_storage_context->GetStorageNamespace(id)); + WebStorageNamespace* web_storage_namespace = + WebStorageNamespace::createSessionStorageNamespace(); + return new StorageNamespace(dom_storage_context, web_storage_namespace, id, + false); +} + +StorageNamespace::StorageNamespace(DOMStorageContext* dom_storage_context, + WebStorageNamespace* storage_namespace, + int64 id, bool is_local_storage) + : dom_storage_context_(dom_storage_context), + storage_namespace_(storage_namespace), + id_(id), + is_local_storage_(is_local_storage) { + DCHECK(dom_storage_context_); + DCHECK(storage_namespace_); + dom_storage_context_->RegisterStorageNamespace(this); +} + +StorageNamespace::~StorageNamespace() { + dom_storage_context_->UnregisterStorageNamespace(this); + + OriginToStorageAreaMap::iterator iter = origin_to_storage_area_.begin(); + OriginToStorageAreaMap::iterator end = origin_to_storage_area_.end(); + while (iter != end) { + dom_storage_context_->UnregisterStorageArea(iter->second); + delete iter->second; + ++iter; + } +} + +StorageArea* StorageNamespace::GetStorageArea(const string16& origin) { + // 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; + + // We need to create a new one. + int64 id = dom_storage_context_->AllocateStorageAreaId(); + DCHECK(!dom_storage_context_->GetStorageArea(id)); + WebStorageArea* web_storage_area = + storage_namespace_->createStorageArea(origin); + StorageArea* storage_area = new StorageArea(origin, web_storage_area, id); + origin_to_storage_area_[origin] = storage_area; + dom_storage_context_->RegisterStorageArea(storage_area); + return storage_area; +} + +StorageNamespace* StorageNamespace::Copy() { + DCHECK(!is_local_storage_); + int64 id = dom_storage_context_->AllocateStorageNamespaceId(); + DCHECK(!dom_storage_context_->GetStorageNamespace(id)); + WebStorageNamespace* new_storage_namespace = storage_namespace_->copy(); + return new StorageNamespace(dom_storage_context_, new_storage_namespace, id, + is_local_storage_); +} + +void StorageNamespace::Close() { + storage_namespace_->close(); +} diff --git a/chrome/browser/in_process_webkit/storage_namespace.h b/chrome/browser/in_process_webkit/storage_namespace.h new file mode 100644 index 0000000..4018f8f --- /dev/null +++ b/chrome/browser/in_process_webkit/storage_namespace.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 CHROME_BROWSER_IN_PROCESS_WEBKIT_STORAGE_NAMESPACE_H_ +#define CHROME_BROWSER_IN_PROCESS_WEBKIT_STORAGE_NAMESPACE_H_ + +#include "base/string16.h" +#include "base/hash_tables.h" + +class DOMStorageContext; +class FilePath; +class StorageArea; + +namespace WebKit { +class WebStorageNamespace; +} + +// Only to be used on the WebKit thread. +class StorageNamespace { + public: + static StorageNamespace* CreateLocalStorageNamespace( + DOMStorageContext* dom_storage_context, const FilePath& data_dir_path); + static StorageNamespace* CreateSessionStorageNamespace( + DOMStorageContext* dom_storage_context); + + ~StorageNamespace(); + + StorageArea* GetStorageArea(const string16& origin); + StorageNamespace* Copy(); + void Close(); + + int64 id() const { return id_; } + + private: + // Called by the static factory methods above. + StorageNamespace(DOMStorageContext* dom_storage_context, + WebKit::WebStorageNamespace* web_storage_namespace, + int64 id, bool is_local_storage); + + // All the storage areas we own. + typedef base::hash_map<string16, StorageArea*> OriginToStorageAreaMap; + OriginToStorageAreaMap origin_to_storage_area_; + + // The DOMStorageContext that owns us. + DOMStorageContext* dom_storage_context_; + + // The WebKit storage namespace we manage. + WebKit::WebStorageNamespace* storage_namespace_; + + // Our id. Unique to our parent WebKitContext class. + int64 id_; + + // Is this a local storage namespace. + bool is_local_storage_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(StorageNamespace); +}; + +#endif // CHROME_BROWSER_IN_PROCESS_WEBKIT_STORAGE_NAMESPACE_H_ diff --git a/chrome/browser/in_process_webkit/webkit_context.cc b/chrome/browser/in_process_webkit/webkit_context.cc index e7d7d1a..ae647d6 100644 --- a/chrome/browser/in_process_webkit/webkit_context.cc +++ b/chrome/browser/in_process_webkit/webkit_context.cc @@ -4,10 +4,29 @@ #include "chrome/browser/in_process_webkit/webkit_context.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/in_process_webkit/dom_storage_context.h" + WebKitContext::WebKitContext(const FilePath& data_path, bool is_incognito) : data_path_(data_path), is_incognito_(is_incognito) { } WebKitContext::~WebKitContext() { + // If a dom storage context was ever created, we need to destroy it on the + // WebKit thread. Luckily we're guaranteed that the WebKit thread is still + // alive since the ResourceDispatcherHost (which owns the WebKit thread) goes + // away after all the ResourceMessageFilters and the profiles (i.e. all the + // objects with a reference to us). + if (dom_storage_context_.get()) { + MessageLoop* loop = ChromeThread::GetMessageLoop(ChromeThread::WEBKIT); + loop->DeleteSoon(FROM_HERE, dom_storage_context_.release()); + } +} + +DOMStorageContext* WebKitContext::GetDOMStorageContext() { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); + if (!dom_storage_context_.get()) + dom_storage_context_.reset(new DOMStorageContext(this)); + return dom_storage_context_.get(); } diff --git a/chrome/browser/in_process_webkit/webkit_context.h b/chrome/browser/in_process_webkit/webkit_context.h index 2b84224..ee4c61b 100644 --- a/chrome/browser/in_process_webkit/webkit_context.h +++ b/chrome/browser/in_process_webkit/webkit_context.h @@ -7,6 +7,9 @@ #include "base/file_path.h" #include "base/ref_counted.h" +#include "base/scoped_ptr.h" + +class DOMStorageContext; // There's one WebKitContext per profile. Various DispatcherHost classes // have a pointer to the Context to store shared state. @@ -17,12 +20,19 @@ class WebKitContext : public base::RefCountedThreadSafe<WebKitContext> { const FilePath& data_path() const { return data_path_; } bool is_incognito() const { return is_incognito_; } + // Initialized lazily. Pointer is valid for the lifetime of this instance. + DOMStorageContext* GetDOMStorageContext(); + private: friend class base::RefCountedThreadSafe<WebKitContext>; ~WebKitContext(); - FilePath data_path_; - bool is_incognito_; + // Copies of profile data that can be accessed on any thread. + const FilePath data_path_; + const bool is_incognito_; + + // The state for DOM Storage. + scoped_ptr<DOMStorageContext> dom_storage_context_; DISALLOW_IMPLICIT_CONSTRUCTORS(WebKitContext); }; diff --git a/chrome/browser/in_process_webkit/webkit_thread.cc b/chrome/browser/in_process_webkit/webkit_thread.cc index 96384e9..46b62f4 100644 --- a/chrome/browser/in_process_webkit/webkit_thread.cc +++ b/chrome/browser/in_process_webkit/webkit_thread.cc @@ -27,8 +27,6 @@ void WebKitThread::Shutdown() { DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); DCHECK(io_message_loop_); - // TODO(jorlow): Start flushing LocalStorage? - AutoLock lock(io_message_loop_lock_); io_message_loop_ = NULL; } @@ -48,24 +46,23 @@ bool WebKitThread::PostIOThreadTask( } WebKitThread::InternalWebKitThread::InternalWebKitThread() - : ChromeThread(ChromeThread::WEBKIT), - webkit_client_(NULL) { + : ChromeThread(ChromeThread::WEBKIT) { +} + +WebKitThread::InternalWebKitThread::~InternalWebKitThread() { } void WebKitThread::InternalWebKitThread::Init() { - DCHECK(!webkit_client_); - webkit_client_ = new BrowserWebKitClientImpl; - DCHECK(webkit_client_); - WebKit::initialize(webkit_client_); + DCHECK(!webkit_client_.get()); + webkit_client_.reset(new BrowserWebKitClientImpl); + WebKit::initialize(webkit_client_.get()); // If possible, post initialization tasks to this thread (rather than doing // them now) so we don't block the IO thread any longer than we have to. } void WebKitThread::InternalWebKitThread::CleanUp() { - // TODO(jorlow): Block on LocalStorage being 100% shut down. - DCHECK(webkit_client_); + DCHECK(webkit_client_.get()); WebKit::shutdown(); - delete webkit_client_; } MessageLoop* WebKitThread::InitializeThread() { diff --git a/chrome/browser/in_process_webkit/webkit_thread.h b/chrome/browser/in_process_webkit/webkit_thread.h index 8ab1113..828277c 100644 --- a/chrome/browser/in_process_webkit/webkit_thread.h +++ b/chrome/browser/in_process_webkit/webkit_thread.h @@ -49,14 +49,15 @@ class WebKitThread { class InternalWebKitThread : public ChromeThread { public: InternalWebKitThread(); - virtual ~InternalWebKitThread() { } + virtual ~InternalWebKitThread(); // Does the actual initialization and shutdown of WebKit. Called at the // beginning and end of the thread's lifetime. virtual void Init(); virtual void CleanUp(); private: - BrowserWebKitClientImpl* webkit_client_; + // The WebKitClient implementation. Only access on WebKit thread. + scoped_ptr<BrowserWebKitClientImpl> webkit_client_; }; // Returns the WebKit thread's message loop or NULL if we're in |