OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. |
| 4 |
| 5 #include "chrome/renderer/renderer_webstoragearea_impl.h" |
| 6 |
| 7 #include "chrome/common/render_messages.h" |
| 8 #include "chrome/renderer/render_thread.h" |
| 9 #include "webkit/api/public/WebString.h" |
| 10 |
| 11 RendererWebStorageAreaImpl::RendererWebStorageAreaImpl( |
| 12 int64 namespace_id, |
| 13 const WebKit::WebString& origin) |
| 14 : namespace_id_(namespace_id), |
| 15 origin_(origin), |
| 16 storage_area_id_(kUninitializedStorageAreaId), |
| 17 lock_held_(false), |
| 18 bytes_left_in_quota_(0) { |
| 19 } |
| 20 |
| 21 RendererWebStorageAreaImpl::~RendererWebStorageAreaImpl() { |
| 22 } |
| 23 |
| 24 void RendererWebStorageAreaImpl::lock(bool& invalidate_cache, |
| 25 size_t& bytes_left_in_quota) { |
| 26 EnsureInitializedAndLocked(); |
| 27 } |
| 28 |
| 29 void RendererWebStorageAreaImpl::unlock() { |
| 30 if (storage_area_id_ != kUninitializedStorageAreaId) { |
| 31 RenderThread::current()->Send( |
| 32 new ViewHostMsg_DOMStorageUnlock(storage_area_id_)); |
| 33 } |
| 34 lock_held_ = false; |
| 35 } |
| 36 |
| 37 unsigned RendererWebStorageAreaImpl::length() { |
| 38 EnsureInitializedAndLocked(); |
| 39 // Right now this is always sync. We could cache it, but I can't think of |
| 40 // too many use cases where you'd repeatedly look up length() and not be |
| 41 // doing so many key() lookups that the length() calls are the problem. |
| 42 unsigned length; |
| 43 RenderThread::current()->Send( |
| 44 new ViewHostMsg_DOMStorageLength(storage_area_id_, &length)); |
| 45 return length; |
| 46 } |
| 47 |
| 48 WebKit::WebString RendererWebStorageAreaImpl::key(unsigned index, |
| 49 bool& key_exception) { |
| 50 EnsureInitializedAndLocked(); |
| 51 // Right now this is always sync. We may want to optimize this by fetching |
| 52 // chunks of keys rather than single keys (and flushing the cache on every |
| 53 // mutation of the storage area) since this will most often be used to fetch |
| 54 // all the keys at once. |
| 55 string16 key; |
| 56 RenderThread::current()->Send( |
| 57 new ViewHostMsg_DOMStorageKey(storage_area_id_, index, |
| 58 &key_exception, &key)); |
| 59 return key; |
| 60 } |
| 61 |
| 62 WebKit::WebString RendererWebStorageAreaImpl::getItem( |
| 63 const WebKit::WebString& webkit_key) { |
| 64 EnsureInitializedAndLocked(); |
| 65 string16 key = webkit_key; |
| 66 |
| 67 // Return from our cache if possible. |
| 68 CacheMap::const_iterator iterator = cached_items_.find(key); |
| 69 if (iterator != cached_items_.end()) |
| 70 return iterator->second; |
| 71 if (cached_invalid_items_.find(key) != cached_invalid_items_.end()) |
| 72 return WebKit::WebString(); // Return a "null" string. |
| 73 |
| 74 // The item is not in the cache, so we must do a sync IPC. Afterwards, |
| 75 // add it to the cache. |
| 76 string16 raw_value; |
| 77 bool value_is_null; |
| 78 RenderThread::current()->Send( |
| 79 new ViewHostMsg_DOMStorageGetItem(storage_area_id_, key, |
| 80 &raw_value, &value_is_null)); |
| 81 WebKit::WebString value = value_is_null ? WebKit::WebString() |
| 82 : WebKit::WebString(raw_value); |
| 83 SetCache(key, value); |
| 84 return value; |
| 85 } |
| 86 |
| 87 void RendererWebStorageAreaImpl::setItem(const WebKit::WebString& key, |
| 88 const WebKit::WebString& value, |
| 89 bool& quota_exception) { |
| 90 EnsureInitializedAndLocked(); |
| 91 quota_exception = !UpdateQuota(key, value); |
| 92 if (quota_exception) |
| 93 return; |
| 94 RenderThread::current()->Send( |
| 95 new ViewHostMsg_DOMStorageSetItem(storage_area_id_, key, value)); |
| 96 SetCache(key, value); |
| 97 } |
| 98 |
| 99 void RendererWebStorageAreaImpl::removeItem(const WebKit::WebString& key) { |
| 100 EnsureInitializedAndLocked(); |
| 101 bool update_succeeded = UpdateQuota(key, WebKit::WebString()); |
| 102 DCHECK(update_succeeded); |
| 103 RenderThread::current()->Send( |
| 104 new ViewHostMsg_DOMStorageRemoveItem(storage_area_id_, key)); |
| 105 SetCache(key, WebKit::WebString()); |
| 106 } |
| 107 |
| 108 void RendererWebStorageAreaImpl::clear() { |
| 109 EnsureInitializedAndLocked(); |
| 110 RenderThread::current()->Send( |
| 111 new ViewHostMsg_DOMStorageClear(storage_area_id_, |
| 112 &bytes_left_in_quota_)); |
| 113 // A possible optimization is a flag that says our cache is 100% complete. |
| 114 // This could be set here, and then future gets would never require IPC. |
| 115 cached_items_.clear(); |
| 116 cached_invalid_items_.clear(); |
| 117 } |
| 118 |
| 119 void RendererWebStorageAreaImpl::EnsureInitializedAndLocked() { |
| 120 if (storage_area_id_ == kUninitializedStorageAreaId) { |
| 121 RenderThread::current()->Send( |
| 122 new ViewHostMsg_DOMStorageStorageAreaId(namespace_id_, origin_, |
| 123 &storage_area_id_)); |
| 124 } |
| 125 |
| 126 if (lock_held_) |
| 127 return; |
| 128 |
| 129 bool invalidate_cache; |
| 130 RenderThread::current()->Send( |
| 131 new ViewHostMsg_DOMStorageLock(storage_area_id_, &invalidate_cache, |
| 132 &bytes_left_in_quota_)); |
| 133 lock_held_ = true; |
| 134 if (invalidate_cache) { |
| 135 cached_items_.clear(); |
| 136 cached_invalid_items_.clear(); |
| 137 } |
| 138 } |
| 139 |
| 140 bool RendererWebStorageAreaImpl::UpdateQuota(const WebKit::WebString& key, |
| 141 const WebKit::WebString& value) { |
| 142 // TODO(jorlow): Remove once the bytes_left_in_quota values we're getting |
| 143 // are accurate. |
| 144 return true; |
| 145 |
| 146 size_t existing_bytes = getItem(key).length(); |
| 147 size_t new_bytes = value.length(); |
| 148 |
| 149 if (existing_bytes < new_bytes) { |
| 150 size_t delta = new_bytes - existing_bytes; |
| 151 if (delta > bytes_left_in_quota_) |
| 152 return false; |
| 153 bytes_left_in_quota_ -= delta; |
| 154 } else { |
| 155 size_t delta = existing_bytes - new_bytes; |
| 156 DCHECK(delta + bytes_left_in_quota_ >= bytes_left_in_quota_); |
| 157 bytes_left_in_quota_ += delta; |
| 158 } |
| 159 return true; |
| 160 } |
| 161 |
| 162 void RendererWebStorageAreaImpl::SetCache(const string16& key, |
| 163 const WebKit::WebString& value) { |
| 164 cached_items_.erase(key); |
| 165 cached_invalid_items_.erase(key); |
| 166 |
| 167 if (!value.isNull()) |
| 168 cached_items_[key] = value; |
| 169 else |
| 170 cached_invalid_items_.insert(key); |
| 171 } |
OLD | NEW |