| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/dom_storage/dom_storage_dispatcher.h" | 5 #include "content/renderer/dom_storage/dom_storage_dispatcher.h" |
| 6 | 6 |
| 7 #include <list> | 7 #include <list> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/synchronization/lock.h" | 11 #include "base/synchronization/lock.h" |
| 12 #include "content/common/dom_storage_messages.h" | 12 #include "content/common/dom_storage/dom_storage_messages.h" |
| 13 #include "content/common/dom_storage/dom_storage_types.h" |
| 13 #include "content/renderer/dom_storage/dom_storage_cached_area.h" | 14 #include "content/renderer/dom_storage/dom_storage_cached_area.h" |
| 14 #include "content/renderer/dom_storage/dom_storage_proxy.h" | 15 #include "content/renderer/dom_storage/dom_storage_proxy.h" |
| 15 #include "content/renderer/dom_storage/webstoragearea_impl.h" | 16 #include "content/renderer/dom_storage/webstoragearea_impl.h" |
| 16 #include "content/renderer/dom_storage/webstoragenamespace_impl.h" | 17 #include "content/renderer/dom_storage/webstoragenamespace_impl.h" |
| 17 #include "content/renderer/render_thread_impl.h" | 18 #include "content/renderer/render_thread_impl.h" |
| 18 #include "third_party/WebKit/public/platform/Platform.h" | 19 #include "third_party/WebKit/public/platform/Platform.h" |
| 19 #include "third_party/WebKit/public/web/WebKit.h" | 20 #include "third_party/WebKit/public/web/WebKit.h" |
| 20 #include "third_party/WebKit/public/web/WebStorageEventDispatcher.h" | 21 #include "third_party/WebKit/public/web/WebStorageEventDispatcher.h" |
| 21 #include "webkit/common/dom_storage/dom_storage_types.h" | |
| 22 | |
| 23 using dom_storage::ValuesMap; | |
| 24 | 22 |
| 25 namespace content { | 23 namespace content { |
| 26 | 24 |
| 27 namespace { | 25 namespace { |
| 28 // MessageThrottlingFilter ------------------------------------------- | 26 // MessageThrottlingFilter ------------------------------------------- |
| 29 // Used to limit the number of ipc messages pending completion so we | 27 // Used to limit the number of ipc messages pending completion so we |
| 30 // don't overwhelm the main browser process. When the limit is reached, | 28 // don't overwhelm the main browser process. When the limit is reached, |
| 31 // a synchronous message is sent to flush all pending messages thru. | 29 // a synchronous message is sent to flush all pending messages thru. |
| 32 // We expect to receive an 'ack' for each message sent. This object | 30 // We expect to receive an 'ack' for each message sent. This object |
| 33 // observes receipt of the acks on the IPC thread to decrement a counter. | 31 // observes receipt of the acks on the IPC thread to decrement a counter. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 bool MessageThrottlingFilter::OnMessageReceived(const IPC::Message& message) { | 83 bool MessageThrottlingFilter::OnMessageReceived(const IPC::Message& message) { |
| 86 if (message.type() == DOMStorageMsg_AsyncOperationComplete::ID) { | 84 if (message.type() == DOMStorageMsg_AsyncOperationComplete::ID) { |
| 87 DecrementPendingCount(); | 85 DecrementPendingCount(); |
| 88 DCHECK_LE(0, GetPendingCount()); | 86 DCHECK_LE(0, GetPendingCount()); |
| 89 } | 87 } |
| 90 return false; | 88 return false; |
| 91 } | 89 } |
| 92 } // namespace | 90 } // namespace |
| 93 | 91 |
| 94 // ProxyImpl ----------------------------------------------------- | 92 // ProxyImpl ----------------------------------------------------- |
| 95 // An implementation of the DomStorageProxy interface in terms of IPC. | 93 // An implementation of the DOMStorageProxy interface in terms of IPC. |
| 96 // This class also manages the collection of cached areas and pending | 94 // This class also manages the collection of cached areas and pending |
| 97 // operations awaiting completion callbacks. | 95 // operations awaiting completion callbacks. |
| 98 class DomStorageDispatcher::ProxyImpl : public DomStorageProxy { | 96 class DomStorageDispatcher::ProxyImpl : public DOMStorageProxy { |
| 99 public: | 97 public: |
| 100 explicit ProxyImpl(RenderThreadImpl* sender); | 98 explicit ProxyImpl(RenderThreadImpl* sender); |
| 101 | 99 |
| 102 // Methods for use by DomStorageDispatcher directly. | 100 // Methods for use by DomStorageDispatcher directly. |
| 103 DomStorageCachedArea* OpenCachedArea( | 101 DOMStorageCachedArea* OpenCachedArea( |
| 104 int64 namespace_id, const GURL& origin); | 102 int64 namespace_id, const GURL& origin); |
| 105 void CloseCachedArea(DomStorageCachedArea* area); | 103 void CloseCachedArea(DOMStorageCachedArea* area); |
| 106 DomStorageCachedArea* LookupCachedArea( | 104 DOMStorageCachedArea* LookupCachedArea( |
| 107 int64 namespace_id, const GURL& origin); | 105 int64 namespace_id, const GURL& origin); |
| 108 void CompleteOnePendingCallback(bool success); | 106 void CompleteOnePendingCallback(bool success); |
| 109 void Shutdown(); | 107 void Shutdown(); |
| 110 | 108 |
| 111 // DomStorageProxy interface for use by DomStorageCachedArea. | 109 // DOMStorageProxy interface for use by DOMStorageCachedArea. |
| 112 virtual void LoadArea(int connection_id, ValuesMap* values, | 110 virtual void LoadArea(int connection_id, DOMStorageValuesMap* values, |
| 113 const CompletionCallback& callback) OVERRIDE; | 111 const CompletionCallback& callback) OVERRIDE; |
| 114 virtual void SetItem(int connection_id, const string16& key, | 112 virtual void SetItem(int connection_id, const string16& key, |
| 115 const string16& value, const GURL& page_url, | 113 const string16& value, const GURL& page_url, |
| 116 const CompletionCallback& callback) OVERRIDE; | 114 const CompletionCallback& callback) OVERRIDE; |
| 117 virtual void RemoveItem(int connection_id, const string16& key, | 115 virtual void RemoveItem(int connection_id, const string16& key, |
| 118 const GURL& page_url, | 116 const GURL& page_url, |
| 119 const CompletionCallback& callback) OVERRIDE; | 117 const CompletionCallback& callback) OVERRIDE; |
| 120 virtual void ClearArea(int connection_id, | 118 virtual void ClearArea(int connection_id, |
| 121 const GURL& page_url, | 119 const GURL& page_url, |
| 122 const CompletionCallback& callback) OVERRIDE; | 120 const CompletionCallback& callback) OVERRIDE; |
| 123 | 121 |
| 124 private: | 122 private: |
| 125 // Struct to hold references to our contained areas and | 123 // Struct to hold references to our contained areas and |
| 126 // to keep track of how many tabs have a given area open. | 124 // to keep track of how many tabs have a given area open. |
| 127 struct CachedAreaHolder { | 125 struct CachedAreaHolder { |
| 128 scoped_refptr<DomStorageCachedArea> area_; | 126 scoped_refptr<DOMStorageCachedArea> area_; |
| 129 int open_count_; | 127 int open_count_; |
| 130 CachedAreaHolder() : open_count_(0) {} | 128 CachedAreaHolder() : open_count_(0) {} |
| 131 CachedAreaHolder(DomStorageCachedArea* area, int count) | 129 CachedAreaHolder(DOMStorageCachedArea* area, int count) |
| 132 : area_(area), open_count_(count) {} | 130 : area_(area), open_count_(count) {} |
| 133 }; | 131 }; |
| 134 typedef std::map<std::string, CachedAreaHolder> CachedAreaMap; | 132 typedef std::map<std::string, CachedAreaHolder> CachedAreaMap; |
| 135 typedef std::list<CompletionCallback> CallbackList; | 133 typedef std::list<CompletionCallback> CallbackList; |
| 136 | 134 |
| 137 virtual ~ProxyImpl() { | 135 virtual ~ProxyImpl() { |
| 138 } | 136 } |
| 139 | 137 |
| 140 // Sudden termination is disabled when there are callbacks pending | 138 // Sudden termination is disabled when there are callbacks pending |
| 141 // to more reliably commit changes during shutdown. | 139 // to more reliably commit changes during shutdown. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 169 CallbackList pending_callbacks_; | 167 CallbackList pending_callbacks_; |
| 170 scoped_refptr<MessageThrottlingFilter> throttling_filter_; | 168 scoped_refptr<MessageThrottlingFilter> throttling_filter_; |
| 171 }; | 169 }; |
| 172 | 170 |
| 173 DomStorageDispatcher::ProxyImpl::ProxyImpl(RenderThreadImpl* sender) | 171 DomStorageDispatcher::ProxyImpl::ProxyImpl(RenderThreadImpl* sender) |
| 174 : sender_(sender), | 172 : sender_(sender), |
| 175 throttling_filter_(new MessageThrottlingFilter(sender)) { | 173 throttling_filter_(new MessageThrottlingFilter(sender)) { |
| 176 sender_->AddFilter(throttling_filter_.get()); | 174 sender_->AddFilter(throttling_filter_.get()); |
| 177 } | 175 } |
| 178 | 176 |
| 179 DomStorageCachedArea* DomStorageDispatcher::ProxyImpl::OpenCachedArea( | 177 DOMStorageCachedArea* DomStorageDispatcher::ProxyImpl::OpenCachedArea( |
| 180 int64 namespace_id, const GURL& origin) { | 178 int64 namespace_id, const GURL& origin) { |
| 181 std::string key = GetCachedAreaKey(namespace_id, origin); | 179 std::string key = GetCachedAreaKey(namespace_id, origin); |
| 182 if (CachedAreaHolder* holder = GetAreaHolder(key)) { | 180 if (CachedAreaHolder* holder = GetAreaHolder(key)) { |
| 183 ++(holder->open_count_); | 181 ++(holder->open_count_); |
| 184 return holder->area_.get(); | 182 return holder->area_.get(); |
| 185 } | 183 } |
| 186 scoped_refptr<DomStorageCachedArea> area = | 184 scoped_refptr<DOMStorageCachedArea> area = |
| 187 new DomStorageCachedArea(namespace_id, origin, this); | 185 new DOMStorageCachedArea(namespace_id, origin, this); |
| 188 cached_areas_[key] = CachedAreaHolder(area.get(), 1); | 186 cached_areas_[key] = CachedAreaHolder(area.get(), 1); |
| 189 return area.get(); | 187 return area.get(); |
| 190 } | 188 } |
| 191 | 189 |
| 192 void DomStorageDispatcher::ProxyImpl::CloseCachedArea( | 190 void DomStorageDispatcher::ProxyImpl::CloseCachedArea( |
| 193 DomStorageCachedArea* area) { | 191 DOMStorageCachedArea* area) { |
| 194 std::string key = GetCachedAreaKey(area->namespace_id(), area->origin()); | 192 std::string key = GetCachedAreaKey(area->namespace_id(), area->origin()); |
| 195 CachedAreaHolder* holder = GetAreaHolder(key); | 193 CachedAreaHolder* holder = GetAreaHolder(key); |
| 196 DCHECK(holder); | 194 DCHECK(holder); |
| 197 DCHECK_EQ(holder->area_.get(), area); | 195 DCHECK_EQ(holder->area_.get(), area); |
| 198 DCHECK_GT(holder->open_count_, 0); | 196 DCHECK_GT(holder->open_count_, 0); |
| 199 if (--(holder->open_count_) == 0) { | 197 if (--(holder->open_count_) == 0) { |
| 200 cached_areas_.erase(key); | 198 cached_areas_.erase(key); |
| 201 } | 199 } |
| 202 } | 200 } |
| 203 | 201 |
| 204 DomStorageCachedArea* DomStorageDispatcher::ProxyImpl::LookupCachedArea( | 202 DOMStorageCachedArea* DomStorageDispatcher::ProxyImpl::LookupCachedArea( |
| 205 int64 namespace_id, const GURL& origin) { | 203 int64 namespace_id, const GURL& origin) { |
| 206 std::string key = GetCachedAreaKey(namespace_id, origin); | 204 std::string key = GetCachedAreaKey(namespace_id, origin); |
| 207 CachedAreaHolder* holder = GetAreaHolder(key); | 205 CachedAreaHolder* holder = GetAreaHolder(key); |
| 208 if (!holder) | 206 if (!holder) |
| 209 return NULL; | 207 return NULL; |
| 210 return holder->area_.get(); | 208 return holder->area_.get(); |
| 211 } | 209 } |
| 212 | 210 |
| 213 void DomStorageDispatcher::ProxyImpl::CompleteOnePendingCallback(bool success) { | 211 void DomStorageDispatcher::ProxyImpl::CompleteOnePendingCallback(bool success) { |
| 214 PopPendingCallback().Run(success); | 212 PopPendingCallback().Run(success); |
| 215 } | 213 } |
| 216 | 214 |
| 217 void DomStorageDispatcher::ProxyImpl::Shutdown() { | 215 void DomStorageDispatcher::ProxyImpl::Shutdown() { |
| 218 throttling_filter_->Shutdown(); | 216 throttling_filter_->Shutdown(); |
| 219 sender_->RemoveFilter(throttling_filter_.get()); | 217 sender_->RemoveFilter(throttling_filter_.get()); |
| 220 sender_ = NULL; | 218 sender_ = NULL; |
| 221 cached_areas_.clear(); | 219 cached_areas_.clear(); |
| 222 pending_callbacks_.clear(); | 220 pending_callbacks_.clear(); |
| 223 } | 221 } |
| 224 | 222 |
| 225 void DomStorageDispatcher::ProxyImpl::LoadArea( | 223 void DomStorageDispatcher::ProxyImpl::LoadArea( |
| 226 int connection_id, ValuesMap* values, | 224 int connection_id, DOMStorageValuesMap* values, |
| 227 const CompletionCallback& callback) { | 225 const CompletionCallback& callback) { |
| 228 PushPendingCallback(callback); | 226 PushPendingCallback(callback); |
| 229 throttling_filter_->SendThrottled(new DOMStorageHostMsg_LoadStorageArea( | 227 throttling_filter_->SendThrottled(new DOMStorageHostMsg_LoadStorageArea( |
| 230 connection_id, values)); | 228 connection_id, values)); |
| 231 } | 229 } |
| 232 | 230 |
| 233 void DomStorageDispatcher::ProxyImpl::SetItem( | 231 void DomStorageDispatcher::ProxyImpl::SetItem( |
| 234 int connection_id, const string16& key, | 232 int connection_id, const string16& key, |
| 235 const string16& value, const GURL& page_url, | 233 const string16& value, const GURL& page_url, |
| 236 const CompletionCallback& callback) { | 234 const CompletionCallback& callback) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 258 // DomStorageDispatcher ------------------------------------------------ | 256 // DomStorageDispatcher ------------------------------------------------ |
| 259 | 257 |
| 260 DomStorageDispatcher::DomStorageDispatcher() | 258 DomStorageDispatcher::DomStorageDispatcher() |
| 261 : proxy_(new ProxyImpl(RenderThreadImpl::current())) { | 259 : proxy_(new ProxyImpl(RenderThreadImpl::current())) { |
| 262 } | 260 } |
| 263 | 261 |
| 264 DomStorageDispatcher::~DomStorageDispatcher() { | 262 DomStorageDispatcher::~DomStorageDispatcher() { |
| 265 proxy_->Shutdown(); | 263 proxy_->Shutdown(); |
| 266 } | 264 } |
| 267 | 265 |
| 268 scoped_refptr<DomStorageCachedArea> DomStorageDispatcher::OpenCachedArea( | 266 scoped_refptr<DOMStorageCachedArea> DomStorageDispatcher::OpenCachedArea( |
| 269 int connection_id, int64 namespace_id, const GURL& origin) { | 267 int connection_id, int64 namespace_id, const GURL& origin) { |
| 270 RenderThreadImpl::current()->Send( | 268 RenderThreadImpl::current()->Send( |
| 271 new DOMStorageHostMsg_OpenStorageArea( | 269 new DOMStorageHostMsg_OpenStorageArea( |
| 272 connection_id, namespace_id, origin)); | 270 connection_id, namespace_id, origin)); |
| 273 return proxy_->OpenCachedArea(namespace_id, origin); | 271 return proxy_->OpenCachedArea(namespace_id, origin); |
| 274 } | 272 } |
| 275 | 273 |
| 276 void DomStorageDispatcher::CloseCachedArea( | 274 void DomStorageDispatcher::CloseCachedArea( |
| 277 int connection_id, DomStorageCachedArea* area) { | 275 int connection_id, DOMStorageCachedArea* area) { |
| 278 RenderThreadImpl::current()->Send( | 276 RenderThreadImpl::current()->Send( |
| 279 new DOMStorageHostMsg_CloseStorageArea(connection_id)); | 277 new DOMStorageHostMsg_CloseStorageArea(connection_id)); |
| 280 proxy_->CloseCachedArea(area); | 278 proxy_->CloseCachedArea(area); |
| 281 } | 279 } |
| 282 | 280 |
| 283 bool DomStorageDispatcher::OnMessageReceived(const IPC::Message& msg) { | 281 bool DomStorageDispatcher::OnMessageReceived(const IPC::Message& msg) { |
| 284 bool handled = true; | 282 bool handled = true; |
| 285 IPC_BEGIN_MESSAGE_MAP(DomStorageDispatcher, msg) | 283 IPC_BEGIN_MESSAGE_MAP(DomStorageDispatcher, msg) |
| 286 IPC_MESSAGE_HANDLER(DOMStorageMsg_Event, OnStorageEvent) | 284 IPC_MESSAGE_HANDLER(DOMStorageMsg_Event, OnStorageEvent) |
| 287 IPC_MESSAGE_HANDLER(DOMStorageMsg_AsyncOperationComplete, | 285 IPC_MESSAGE_HANDLER(DOMStorageMsg_AsyncOperationComplete, |
| 288 OnAsyncOperationComplete) | 286 OnAsyncOperationComplete) |
| 289 IPC_MESSAGE_UNHANDLED(handled = false) | 287 IPC_MESSAGE_UNHANDLED(handled = false) |
| 290 IPC_END_MESSAGE_MAP() | 288 IPC_END_MESSAGE_MAP() |
| 291 return handled; | 289 return handled; |
| 292 } | 290 } |
| 293 | 291 |
| 294 void DomStorageDispatcher::OnStorageEvent( | 292 void DomStorageDispatcher::OnStorageEvent( |
| 295 const DOMStorageMsg_Event_Params& params) { | 293 const DOMStorageMsg_Event_Params& params) { |
| 296 RenderThreadImpl::current()->EnsureWebKitInitialized(); | 294 RenderThreadImpl::current()->EnsureWebKitInitialized(); |
| 297 | 295 |
| 298 bool originated_in_process = params.connection_id != 0; | 296 bool originated_in_process = params.connection_id != 0; |
| 299 WebStorageAreaImpl* originating_area = NULL; | 297 WebStorageAreaImpl* originating_area = NULL; |
| 300 if (originated_in_process) { | 298 if (originated_in_process) { |
| 301 originating_area = WebStorageAreaImpl::FromConnectionId( | 299 originating_area = WebStorageAreaImpl::FromConnectionId( |
| 302 params.connection_id); | 300 params.connection_id); |
| 303 } else { | 301 } else { |
| 304 DomStorageCachedArea* cached_area = proxy_->LookupCachedArea( | 302 DOMStorageCachedArea* cached_area = proxy_->LookupCachedArea( |
| 305 params.namespace_id, params.origin); | 303 params.namespace_id, params.origin); |
| 306 if (cached_area) | 304 if (cached_area) |
| 307 cached_area->ApplyMutation(params.key, params.new_value); | 305 cached_area->ApplyMutation(params.key, params.new_value); |
| 308 } | 306 } |
| 309 | 307 |
| 310 if (params.namespace_id == dom_storage::kLocalStorageNamespaceId) { | 308 if (params.namespace_id == kLocalStorageNamespaceId) { |
| 311 WebKit::WebStorageEventDispatcher::dispatchLocalStorageEvent( | 309 WebKit::WebStorageEventDispatcher::dispatchLocalStorageEvent( |
| 312 params.key, | 310 params.key, |
| 313 params.old_value, | 311 params.old_value, |
| 314 params.new_value, | 312 params.new_value, |
| 315 params.origin, | 313 params.origin, |
| 316 params.page_url, | 314 params.page_url, |
| 317 originating_area, | 315 originating_area, |
| 318 originated_in_process); | 316 originated_in_process); |
| 319 } else { | 317 } else { |
| 320 WebStorageNamespaceImpl | 318 WebStorageNamespaceImpl |
| 321 session_namespace_for_event_dispatch(params.namespace_id); | 319 session_namespace_for_event_dispatch(params.namespace_id); |
| 322 WebKit::WebStorageEventDispatcher::dispatchSessionStorageEvent( | 320 WebKit::WebStorageEventDispatcher::dispatchSessionStorageEvent( |
| 323 params.key, | 321 params.key, |
| 324 params.old_value, | 322 params.old_value, |
| 325 params.new_value, | 323 params.new_value, |
| 326 params.origin, | 324 params.origin, |
| 327 params.page_url, | 325 params.page_url, |
| 328 session_namespace_for_event_dispatch, | 326 session_namespace_for_event_dispatch, |
| 329 originating_area, | 327 originating_area, |
| 330 originated_in_process); | 328 originated_in_process); |
| 331 } | 329 } |
| 332 } | 330 } |
| 333 | 331 |
| 334 void DomStorageDispatcher::OnAsyncOperationComplete(bool success) { | 332 void DomStorageDispatcher::OnAsyncOperationComplete(bool success) { |
| 335 proxy_->CompleteOnePendingCallback(success); | 333 proxy_->CompleteOnePendingCallback(success); |
| 336 } | 334 } |
| 337 | 335 |
| 338 } // namespace content | 336 } // namespace content |
| OLD | NEW |