summaryrefslogtreecommitdiffstats
path: root/chrome/renderer
diff options
context:
space:
mode:
authorjorlow@chromium.org <jorlow@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-24 01:22:51 +0000
committerjorlow@chromium.org <jorlow@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-24 01:22:51 +0000
commit2a10f681c582df15719956061b6742a55bccb46a (patch)
tree4e4ee689cafbecb9b211f437f478b7588f6c05c2 /chrome/renderer
parent4f9b2a7e42fc567073f4999a888b3140bec460bb (diff)
downloadchromium_src-2a10f681c582df15719956061b6742a55bccb46a.zip
chromium_src-2a10f681c582df15719956061b6742a55bccb46a.tar.gz
chromium_src-2a10f681c582df15719956061b6742a55bccb46a.tar.bz2
The final CL for plumbing DOM Storage.
Add webKitClient plumbing for getting/creating storage namespaces. Add a chromium implementation for WebStorageArea and WebStorageNamespace which communicates via IPC with the dom_storage_dispatcher_host in the browser process. Flesh out the StorageAreaProxy and StorageNamespaceProxy to use the aforementioned implementations. The WebStorageArea implementation includes decently aggressive caching optimizations. There's still a lot of work to do, though. BUG=4360 TEST=none Review URL: http://codereview.chromium.org/147248 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21495 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r--chrome/renderer/renderer_webkitclient_impl.cc17
-rw-r--r--chrome/renderer/renderer_webkitclient_impl.h3
-rw-r--r--chrome/renderer/renderer_webstoragearea_impl.cc171
-rw-r--r--chrome/renderer/renderer_webstoragearea_impl.h76
-rw-r--r--chrome/renderer/renderer_webstoragenamespace_impl.cc65
-rw-r--r--chrome/renderer/renderer_webstoragenamespace_impl.h35
6 files changed, 367 insertions, 0 deletions
diff --git a/chrome/renderer/renderer_webkitclient_impl.cc b/chrome/renderer/renderer_webkitclient_impl.cc
index 05e56fb..a863971 100644
--- a/chrome/renderer/renderer_webkitclient_impl.cc
+++ b/chrome/renderer/renderer_webkitclient_impl.cc
@@ -10,6 +10,7 @@
#include "chrome/plugin/npobject_util.h"
#include "chrome/renderer/net/render_dns_master.h"
#include "chrome/renderer/render_thread.h"
+#include "chrome/renderer/renderer_webstoragenamespace_impl.h"
#include "chrome/renderer/visitedlink_slave.h"
#include "webkit/api/public/WebString.h"
#include "webkit/api/public/WebURL.h"
@@ -20,6 +21,8 @@
#include "chrome/renderer/renderer_sandbox_support_linux.h"
#endif
+using WebKit::WebStorageArea;
+using WebKit::WebStorageNamespace;
using WebKit::WebString;
using WebKit::WebURL;
@@ -100,6 +103,20 @@ void RendererWebKitClientImpl::suddenTerminationChanged(bool enabled) {
thread->Send(new ViewHostMsg_SuddenTerminationChanged(enabled));
}
+WebStorageNamespace* RendererWebKitClientImpl::createLocalStorageNamespace(
+ const WebString& path) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
+ return WebStorageNamespace::createLocalStorageNamespace(path);
+ // The browser process decides the path, so ignore that param.
+ return new RendererWebStorageNamespaceImpl(true);
+}
+
+WebStorageNamespace* RendererWebKitClientImpl::createSessionStorageNamespace() {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
+ return WebStorageNamespace::createSessionStorageNamespace();
+ return new RendererWebStorageNamespaceImpl(false);
+}
+
//------------------------------------------------------------------------------
WebString RendererWebKitClientImpl::MimeRegistry::mimeTypeForExtension(
diff --git a/chrome/renderer/renderer_webkitclient_impl.h b/chrome/renderer/renderer_webkitclient_impl.h
index 3f4d5cf..0190027 100644
--- a/chrome/renderer/renderer_webkitclient_impl.h
+++ b/chrome/renderer/renderer_webkitclient_impl.h
@@ -36,6 +36,9 @@ class RendererWebKitClientImpl : public webkit_glue::WebKitClientImpl {
virtual void prefetchHostName(const WebKit::WebString&);
virtual WebKit::WebString defaultLocale();
virtual void suddenTerminationChanged(bool enabled);
+ virtual WebKit::WebStorageNamespace* createLocalStorageNamespace(
+ const WebKit::WebString& path);
+ virtual WebKit::WebStorageNamespace* createSessionStorageNamespace();
private:
class MimeRegistry : public webkit_glue::SimpleWebMimeRegistryImpl {
diff --git a/chrome/renderer/renderer_webstoragearea_impl.cc b/chrome/renderer/renderer_webstoragearea_impl.cc
new file mode 100644
index 0000000..c438cdfe
--- /dev/null
+++ b/chrome/renderer/renderer_webstoragearea_impl.cc
@@ -0,0 +1,171 @@
+// 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/renderer/renderer_webstoragearea_impl.h"
+
+#include "chrome/common/render_messages.h"
+#include "chrome/renderer/render_thread.h"
+#include "webkit/api/public/WebString.h"
+
+RendererWebStorageAreaImpl::RendererWebStorageAreaImpl(
+ int64 namespace_id,
+ const WebKit::WebString& origin)
+ : namespace_id_(namespace_id),
+ origin_(origin),
+ storage_area_id_(kUninitializedStorageAreaId),
+ lock_held_(false),
+ bytes_left_in_quota_(0) {
+}
+
+RendererWebStorageAreaImpl::~RendererWebStorageAreaImpl() {
+}
+
+void RendererWebStorageAreaImpl::lock(bool& invalidate_cache,
+ size_t& bytes_left_in_quota) {
+ EnsureInitializedAndLocked();
+}
+
+void RendererWebStorageAreaImpl::unlock() {
+ if (storage_area_id_ != kUninitializedStorageAreaId) {
+ RenderThread::current()->Send(
+ new ViewHostMsg_DOMStorageUnlock(storage_area_id_));
+ }
+ lock_held_ = false;
+}
+
+unsigned RendererWebStorageAreaImpl::length() {
+ EnsureInitializedAndLocked();
+ // Right now this is always sync. We could cache it, but I can't think of
+ // too many use cases where you'd repeatedly look up length() and not be
+ // doing so many key() lookups that the length() calls are the problem.
+ unsigned length;
+ RenderThread::current()->Send(
+ new ViewHostMsg_DOMStorageLength(storage_area_id_, &length));
+ return length;
+}
+
+WebKit::WebString RendererWebStorageAreaImpl::key(unsigned index,
+ bool& key_exception) {
+ EnsureInitializedAndLocked();
+ // Right now this is always sync. We may want to optimize this by fetching
+ // chunks of keys rather than single keys (and flushing the cache on every
+ // mutation of the storage area) since this will most often be used to fetch
+ // all the keys at once.
+ string16 key;
+ RenderThread::current()->Send(
+ new ViewHostMsg_DOMStorageKey(storage_area_id_, index,
+ &key_exception, &key));
+ return key;
+}
+
+WebKit::WebString RendererWebStorageAreaImpl::getItem(
+ const WebKit::WebString& webkit_key) {
+ EnsureInitializedAndLocked();
+ string16 key = webkit_key;
+
+ // Return from our cache if possible.
+ CacheMap::const_iterator iterator = cached_items_.find(key);
+ if (iterator != cached_items_.end())
+ return iterator->second;
+ if (cached_invalid_items_.find(key) != cached_invalid_items_.end())
+ return WebKit::WebString(); // Return a "null" string.
+
+ // The item is not in the cache, so we must do a sync IPC. Afterwards,
+ // add it to the cache.
+ string16 raw_value;
+ bool value_is_null;
+ RenderThread::current()->Send(
+ new ViewHostMsg_DOMStorageGetItem(storage_area_id_, key,
+ &raw_value, &value_is_null));
+ WebKit::WebString value = value_is_null ? WebKit::WebString()
+ : WebKit::WebString(raw_value);
+ SetCache(key, value);
+ return value;
+}
+
+void RendererWebStorageAreaImpl::setItem(const WebKit::WebString& key,
+ const WebKit::WebString& value,
+ bool& quota_exception) {
+ EnsureInitializedAndLocked();
+ quota_exception = !UpdateQuota(key, value);
+ if (quota_exception)
+ return;
+ RenderThread::current()->Send(
+ new ViewHostMsg_DOMStorageSetItem(storage_area_id_, key, value));
+ SetCache(key, value);
+}
+
+void RendererWebStorageAreaImpl::removeItem(const WebKit::WebString& key) {
+ EnsureInitializedAndLocked();
+ bool update_succeeded = UpdateQuota(key, WebKit::WebString());
+ DCHECK(update_succeeded);
+ RenderThread::current()->Send(
+ new ViewHostMsg_DOMStorageRemoveItem(storage_area_id_, key));
+ SetCache(key, WebKit::WebString());
+}
+
+void RendererWebStorageAreaImpl::clear() {
+ EnsureInitializedAndLocked();
+ RenderThread::current()->Send(
+ new ViewHostMsg_DOMStorageClear(storage_area_id_,
+ &bytes_left_in_quota_));
+ // A possible optimization is a flag that says our cache is 100% complete.
+ // This could be set here, and then future gets would never require IPC.
+ cached_items_.clear();
+ cached_invalid_items_.clear();
+}
+
+void RendererWebStorageAreaImpl::EnsureInitializedAndLocked() {
+ if (storage_area_id_ == kUninitializedStorageAreaId) {
+ RenderThread::current()->Send(
+ new ViewHostMsg_DOMStorageStorageAreaId(namespace_id_, origin_,
+ &storage_area_id_));
+ }
+
+ if (lock_held_)
+ return;
+
+ bool invalidate_cache;
+ RenderThread::current()->Send(
+ new ViewHostMsg_DOMStorageLock(storage_area_id_, &invalidate_cache,
+ &bytes_left_in_quota_));
+ lock_held_ = true;
+ if (invalidate_cache) {
+ cached_items_.clear();
+ cached_invalid_items_.clear();
+ }
+}
+
+bool RendererWebStorageAreaImpl::UpdateQuota(const WebKit::WebString& key,
+ const WebKit::WebString& value) {
+ // TODO(jorlow): Remove once the bytes_left_in_quota values we're getting
+ // are accurate.
+ return true;
+
+ size_t existing_bytes = getItem(key).length();
+ size_t new_bytes = value.length();
+
+ if (existing_bytes < new_bytes) {
+ size_t delta = new_bytes - existing_bytes;
+ if (delta > bytes_left_in_quota_)
+ return false;
+ bytes_left_in_quota_ -= delta;
+ } else {
+ size_t delta = existing_bytes - new_bytes;
+ DCHECK(delta + bytes_left_in_quota_ >= bytes_left_in_quota_);
+ bytes_left_in_quota_ += delta;
+ }
+ return true;
+}
+
+void RendererWebStorageAreaImpl::SetCache(const string16& key,
+ const WebKit::WebString& value) {
+ cached_items_.erase(key);
+ cached_invalid_items_.erase(key);
+
+ if (!value.isNull())
+ cached_items_[key] = value;
+ else
+ cached_invalid_items_.insert(key);
+}
diff --git a/chrome/renderer/renderer_webstoragearea_impl.h b/chrome/renderer/renderer_webstoragearea_impl.h
new file mode 100644
index 0000000..0a313c2
--- /dev/null
+++ b/chrome/renderer/renderer_webstoragearea_impl.h
@@ -0,0 +1,76 @@
+// 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_RENDERER_RENDERER_WEBSTORAGEAREA_IMPL_H_
+#define CHROME_RENDERER_RENDERER_WEBSTORAGEAREA_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/hash_tables.h"
+#include "base/string16.h"
+#include "webkit/api/public/WebStorageArea.h"
+#include "webkit/api/public/WebString.h"
+
+class RendererWebStorageAreaImpl : public WebKit::WebStorageArea {
+ public:
+ RendererWebStorageAreaImpl(int64 namespace_id,
+ const WebKit::WebString& origin);
+ virtual ~RendererWebStorageAreaImpl();
+
+ // See WebStorageArea.h for documentation on these functions.
+ virtual void lock(bool& invalidate_cache, size_t& bytes_left_in_quota);
+ virtual void unlock();
+ virtual unsigned length();
+ virtual WebKit::WebString key(unsigned index, bool& key_exception);
+ virtual WebKit::WebString getItem(const WebKit::WebString& key);
+ virtual void setItem(const WebKit::WebString& key,
+ const WebKit::WebString& value,
+ bool& quota_exception);
+ virtual void removeItem(const WebKit::WebString& key);
+ virtual void clear();
+
+ private:
+ // Calls lock if we haven't already done so, and also gets a storage_area_id
+ // if we haven't done so. Fetches quota and cache invalidation information
+ // while locking. Only call on the WebKit thread.
+ void EnsureInitializedAndLocked();
+
+ // Update our quota calculation. Returns true if we updated the quota.
+ // Returns false if we couldn't update because we would have exceeded the
+ // quota. If an item is not in our cache, it'll require a getItem IPC in
+ // order to determine the existing value's size.
+ bool UpdateQuota(const WebKit::WebString& key,
+ const WebKit::WebString& value);
+
+ // Set a key/value pair in our cache.
+ void SetCache(const string16& key, const WebKit::WebString& value);
+
+ // Used for initialization or storage_area_id_.
+ int64 namespace_id_;
+ string16 origin_;
+
+ // The ID we use for all IPC. Initialized lazily.
+ int64 storage_area_id_;
+
+ // storage_area_id_ should equal this iff its unitialized.
+ static const int64 kUninitializedStorageAreaId = -1;
+
+ // Do we currently hold the lock on this storage area?
+ bool lock_held_;
+
+ // We track how many bytes are left in the quota between lock and unlock
+ // calls. This allows us to avoid sync IPC on setItem.
+ size_t bytes_left_in_quota_;
+
+ // A cache of key/value pairs. If the item exists, it's put in the
+ // cached_items_ map. If not, it's added to the cached_invalid_items_ set.
+ // The lock IPC call tells us when to invalidate these caches.
+ // TODO(jorlow): Instead of a map + a set, use NullableString16 once it's
+ // implemented: http://crbug.com/17343
+ typedef base::hash_map<string16, string16> CacheMap;
+ typedef base::hash_set<string16> CacheSet;
+ CacheMap cached_items_;
+ CacheSet cached_invalid_items_;
+};
+
+#endif // CHROME_RENDERER_WEBSTORAGEAREA_IMPL_H_
diff --git a/chrome/renderer/renderer_webstoragenamespace_impl.cc b/chrome/renderer/renderer_webstoragenamespace_impl.cc
new file mode 100644
index 0000000..453bbcf
--- /dev/null
+++ b/chrome/renderer/renderer_webstoragenamespace_impl.cc
@@ -0,0 +1,65 @@
+// 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/renderer/renderer_webstoragenamespace_impl.h"
+
+#include "chrome/common/render_messages.h"
+#include "chrome/renderer/render_thread.h"
+#include "chrome/renderer/renderer_webstoragearea_impl.h"
+
+RendererWebStorageNamespaceImpl::RendererWebStorageNamespaceImpl(
+ bool is_local_storage)
+ : is_local_storage_(is_local_storage),
+ namespace_id_(kUninitializedNamespaceId) {
+}
+
+RendererWebStorageNamespaceImpl::RendererWebStorageNamespaceImpl(
+ bool is_local_storage, int64 namespace_id)
+ : is_local_storage_(is_local_storage),
+ namespace_id_(namespace_id) {
+ DCHECK(namespace_id_ != kUninitializedNamespaceId);
+}
+
+RendererWebStorageNamespaceImpl::~RendererWebStorageNamespaceImpl() {
+ if (namespace_id_ != kUninitializedNamespaceId)
+ RenderThread::current()->Send(
+ new ViewHostMsg_DOMStorageDerefNamespaceId(namespace_id_));
+}
+
+WebKit::WebStorageArea* RendererWebStorageNamespaceImpl::createStorageArea(
+ const WebKit::WebString& origin) {
+ // This could be done async in the background (started when this class is
+ // first instantiated) rather than lazily on first use, but it's unclear
+ // whether it's worth the complexity.
+ if (namespace_id_ == kUninitializedNamespaceId) {
+ RenderThread::current()->Send(
+ new ViewHostMsg_DOMStorageNamespaceId(is_local_storage_,
+ &namespace_id_));
+ DCHECK(namespace_id_ != kUninitializedNamespaceId);
+ }
+ // Ideally, we'd keep a hash map of origin to these objects. Unfortunately
+ // this doesn't seem practical because there's no good way to ref-count these
+ // objects, and it'd be unclear who owned them. So, instead, we'll pay a
+ // price for an allocaiton and IPC for each.
+ return new RendererWebStorageAreaImpl(namespace_id_, origin);
+}
+
+WebKit::WebStorageNamespace* RendererWebStorageNamespaceImpl::copy() {
+ // If we haven't been used yet, we might as well start out fresh (and lazy).
+ if (namespace_id_ == kUninitializedNamespaceId)
+ return new RendererWebStorageNamespaceImpl(is_local_storage_);
+
+ // This cannot easily be differed because we need a snapshot in time.
+ int64 new_namespace_id;
+ RenderThread::current()->Send(
+ new ViewHostMsg_DOMStorageCloneNamespaceId(namespace_id_,
+ &new_namespace_id));
+ return new RendererWebStorageNamespaceImpl(is_local_storage_,
+ new_namespace_id);
+}
+
+void RendererWebStorageNamespaceImpl::close() {
+ // This is called only on LocalStorage namespaces when WebKit thinks its
+ // shutting down. This has no impact on Chromium.
+}
diff --git a/chrome/renderer/renderer_webstoragenamespace_impl.h b/chrome/renderer/renderer_webstoragenamespace_impl.h
new file mode 100644
index 0000000..7478a67
--- /dev/null
+++ b/chrome/renderer/renderer_webstoragenamespace_impl.h
@@ -0,0 +1,35 @@
+// 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_RENDERER_RENDERER_WEBSTORAGENAMESPACE_IMPL_H_
+#define CHROME_RENDERER_RENDERER_WEBSTORAGENAMESPACE_IMPL_H_
+
+#include "base/basictypes.h"
+#include "webkit/api/public/WebStorageNamespace.h"
+
+class RendererWebStorageNamespaceImpl : public WebKit::WebStorageNamespace {
+ public:
+ explicit RendererWebStorageNamespaceImpl(bool is_local_storage);
+ RendererWebStorageNamespaceImpl(bool is_local_storage, int64 namespace_id);
+
+ // See WebStorageNamespace.h for documentation on these functions.
+ virtual ~RendererWebStorageNamespaceImpl();
+ virtual WebKit::WebStorageArea* createStorageArea(
+ const WebKit::WebString& origin);
+ virtual WebKit::WebStorageNamespace* copy();
+ virtual void close();
+
+ private:
+ // Are we local storage (as opposed to session storage). Used during lazy
+ // initialization of namespace_id_.
+ bool is_local_storage_;
+
+ // Our namespace ID. Lazily initialized.
+ int64 namespace_id_;
+
+ // namespace_id_ should equal this iff its unitialized.
+ static const int64 kUninitializedNamespaceId = -1;
+};
+
+#endif // CHROME_RENDERER_WEBSTORAGENAMESPACE_IMPL_H_