blob: 296d52ec6d7ed57455abc445d5054df3dddebde7 [file] [log] [blame]
Ben Murdochbb1529c2013-08-08 10:24:53 +01001// Copyright 2013 The Chromium Authors. All rights reserved.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Murdochbb1529c2013-08-08 10:24:53 +01005#include "content/browser/dom_storage/dom_storage_host.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01006
Ben Murdochbb1529c2013-08-08 10:24:53 +01007#include "content/browser/dom_storage/dom_storage_area.h"
8#include "content/browser/dom_storage/dom_storage_context_impl.h"
9#include "content/browser/dom_storage/dom_storage_namespace.h"
10#include "content/common/dom_storage/dom_storage_types.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010011#include "url/gurl.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010012
Ben Murdochbb1529c2013-08-08 10:24:53 +010013namespace content {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010014
Ben Murdochbb1529c2013-08-08 10:24:53 +010015DOMStorageHost::DOMStorageHost(DOMStorageContextImpl* context)
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010016 : context_(context) {
17}
18
Ben Murdochbb1529c2013-08-08 10:24:53 +010019DOMStorageHost::~DOMStorageHost() {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010020 AreaMap::const_iterator it = connections_.begin();
21 for (; it != connections_.end(); ++it)
22 it->second.namespace_->CloseStorageArea(it->second.area_.get());
23 connections_.clear(); // Clear prior to releasing the context_
24}
25
Ben Murdochbb1529c2013-08-08 10:24:53 +010026bool DOMStorageHost::OpenStorageArea(int connection_id, int namespace_id,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010027 const GURL& origin) {
28 DCHECK(!GetOpenArea(connection_id));
29 if (GetOpenArea(connection_id))
30 return false; // Indicates the renderer gave us very bad data.
31 NamespaceAndArea references;
32 references.namespace_ = context_->GetStorageNamespace(namespace_id);
Ben Murdoch32409262013-08-07 11:04:47 +010033 if (!references.namespace_.get()) {
34 // TODO(michaeln): Fix crbug/134003 and return false here.
35 // Until then return true to avoid crashing the renderer for
36 // sending a bad message.
37 return true;
38 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010039 references.area_ = references.namespace_->OpenStorageArea(origin);
40 DCHECK(references.area_.get());
41 connections_[connection_id] = references;
42 return true;
43}
44
Ben Murdochbb1529c2013-08-08 10:24:53 +010045void DOMStorageHost::CloseStorageArea(int connection_id) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010046 AreaMap::iterator found = connections_.find(connection_id);
47 if (found == connections_.end())
48 return;
49 found->second.namespace_->CloseStorageArea(found->second.area_.get());
50 connections_.erase(found);
51}
52
Ben Murdochbb1529c2013-08-08 10:24:53 +010053bool DOMStorageHost::ExtractAreaValues(
54 int connection_id, DOMStorageValuesMap* map) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010055 map->clear();
Ben Murdochbb1529c2013-08-08 10:24:53 +010056 DOMStorageArea* area = GetOpenArea(connection_id);
Ben Murdoch32409262013-08-07 11:04:47 +010057 if (!area) {
58 // TODO(michaeln): Fix crbug/134003 and return false here.
59 // Until then return true to avoid crashing the renderer
60 // for sending a bad message.
61 return true;
62 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010063 if (!area->IsLoadedInMemory()) {
Ben Murdochbb1529c2013-08-08 10:24:53 +010064 DOMStorageNamespace* ns = GetNamespace(connection_id);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010065 DCHECK(ns);
Ben Murdochbb1529c2013-08-08 10:24:53 +010066 if (ns->CountInMemoryAreas() > kMaxInMemoryStorageAreas) {
67 ns->PurgeMemory(DOMStorageNamespace::PURGE_UNOPENED);
68 if (ns->CountInMemoryAreas() > kMaxInMemoryStorageAreas)
69 ns->PurgeMemory(DOMStorageNamespace::PURGE_AGGRESSIVE);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010070 }
71 }
72 area->ExtractValues(map);
73 return true;
74}
75
Ben Murdochbb1529c2013-08-08 10:24:53 +010076unsigned DOMStorageHost::GetAreaLength(int connection_id) {
77 DOMStorageArea* area = GetOpenArea(connection_id);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010078 if (!area)
79 return 0;
80 return area->Length();
81}
82
Ben Murdochbb1529c2013-08-08 10:24:53 +010083base::NullableString16 DOMStorageHost::GetAreaKey(int connection_id,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010084 unsigned index) {
Ben Murdochbb1529c2013-08-08 10:24:53 +010085 DOMStorageArea* area = GetOpenArea(connection_id);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010086 if (!area)
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010087 return base::NullableString16();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010088 return area->Key(index);
89}
90
Ben Murdochbb1529c2013-08-08 10:24:53 +010091base::NullableString16 DOMStorageHost::GetAreaItem(int connection_id,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010092 const base::string16& key) {
Ben Murdochbb1529c2013-08-08 10:24:53 +010093 DOMStorageArea* area = GetOpenArea(connection_id);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010094 if (!area)
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010095 return base::NullableString16();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010096 return area->GetItem(key);
97}
98
Ben Murdochbb1529c2013-08-08 10:24:53 +010099bool DOMStorageHost::SetAreaItem(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100100 int connection_id, const base::string16& key,
101 const base::string16& value, const GURL& page_url,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100102 base::NullableString16* old_value) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100103 DOMStorageArea* area = GetOpenArea(connection_id);
Ben Murdoch32409262013-08-07 11:04:47 +0100104 if (!area) {
105 // TODO(michaeln): Fix crbug/134003 and return false here.
106 // Until then return true to allow the renderer to operate
107 // to a limited degree out of its cache.
108 return true;
109 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100110 if (!area->SetItem(key, value, old_value))
111 return false;
112 if (old_value->is_null() || old_value->string() != value)
113 context_->NotifyItemSet(area, key, value, *old_value, page_url);
114 return true;
115}
116
Ben Murdochbb1529c2013-08-08 10:24:53 +0100117bool DOMStorageHost::RemoveAreaItem(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100118 int connection_id, const base::string16& key, const GURL& page_url,
119 base::string16* old_value) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100120 DOMStorageArea* area = GetOpenArea(connection_id);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100121 if (!area)
122 return false;
123 if (!area->RemoveItem(key, old_value))
124 return false;
125 context_->NotifyItemRemoved(area, key, *old_value, page_url);
126 return true;
127}
128
Ben Murdochbb1529c2013-08-08 10:24:53 +0100129bool DOMStorageHost::ClearArea(int connection_id, const GURL& page_url) {
130 DOMStorageArea* area = GetOpenArea(connection_id);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100131 if (!area)
132 return false;
133 if (!area->Clear())
134 return false;
135 context_->NotifyAreaCleared(area, page_url);
136 return true;
137}
138
Ben Murdochbb1529c2013-08-08 10:24:53 +0100139bool DOMStorageHost::HasAreaOpen(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100140 int namespace_id, const GURL& origin) const {
141 AreaMap::const_iterator it = connections_.begin();
142 for (; it != connections_.end(); ++it) {
143 if (namespace_id == it->second.namespace_->namespace_id() &&
144 origin == it->second.area_->origin()) {
145 return true;
146 }
147 }
148 return false;
149}
150
Ben Murdochbb1529c2013-08-08 10:24:53 +0100151DOMStorageArea* DOMStorageHost::GetOpenArea(int connection_id) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100152 AreaMap::iterator found = connections_.find(connection_id);
153 if (found == connections_.end())
154 return NULL;
155 return found->second.area_.get();
156}
157
Ben Murdochbb1529c2013-08-08 10:24:53 +0100158DOMStorageNamespace* DOMStorageHost::GetNamespace(int connection_id) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100159 AreaMap::iterator found = connections_.find(connection_id);
160 if (found == connections_.end())
161 return NULL;
162 return found->second.namespace_.get();
163}
164
165// NamespaceAndArea
166
Ben Murdochbb1529c2013-08-08 10:24:53 +0100167DOMStorageHost::NamespaceAndArea::NamespaceAndArea() {}
168DOMStorageHost::NamespaceAndArea::~NamespaceAndArea() {}
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100169
Ben Murdochbb1529c2013-08-08 10:24:53 +0100170} // namespace content