diff options
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 |