• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/browser/dom_storage/dom_storage_host.h"
6 
7 #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"
11 #include "url/gurl.h"
12 
13 namespace content {
14 
DOMStorageHost(DOMStorageContextImpl * context,int render_process_id)15 DOMStorageHost::DOMStorageHost(DOMStorageContextImpl* context,
16                                int render_process_id)
17     : context_(context),
18       render_process_id_(render_process_id) {
19 }
20 
~DOMStorageHost()21 DOMStorageHost::~DOMStorageHost() {
22   AreaMap::const_iterator it = connections_.begin();
23   for (; it != connections_.end(); ++it)
24     it->second.namespace_->CloseStorageArea(it->second.area_.get());
25   connections_.clear();  // Clear prior to releasing the context_
26 }
27 
OpenStorageArea(int connection_id,int namespace_id,const GURL & origin)28 bool DOMStorageHost::OpenStorageArea(int connection_id, int namespace_id,
29                                      const GURL& origin) {
30   DCHECK(!GetOpenArea(connection_id));
31   if (GetOpenArea(connection_id))
32     return false;  // Indicates the renderer gave us very bad data.
33   NamespaceAndArea references;
34   references.namespace_ = context_->GetStorageNamespace(namespace_id);
35   if (!references.namespace_.get())
36     return false;
37   references.area_ = references.namespace_->OpenStorageArea(origin);
38   DCHECK(references.area_.get());
39   connections_[connection_id] = references;
40   return true;
41 }
42 
CloseStorageArea(int connection_id)43 void DOMStorageHost::CloseStorageArea(int connection_id) {
44   AreaMap::iterator found = connections_.find(connection_id);
45   if (found == connections_.end())
46     return;
47   found->second.namespace_->CloseStorageArea(found->second.area_.get());
48   connections_.erase(found);
49 }
50 
ExtractAreaValues(int connection_id,DOMStorageValuesMap * map,bool * send_log_get_messages)51 bool DOMStorageHost::ExtractAreaValues(
52     int connection_id, DOMStorageValuesMap* map, bool* send_log_get_messages) {
53   map->clear();
54   DOMStorageArea* area = GetOpenArea(connection_id);
55   if (!area)
56     return false;
57   if (!area->IsLoadedInMemory()) {
58     DOMStorageNamespace* ns = GetNamespace(connection_id);
59     DCHECK(ns);
60     if (ns->CountInMemoryAreas() > kMaxInMemoryStorageAreas) {
61       ns->PurgeMemory(DOMStorageNamespace::PURGE_UNOPENED);
62       if (ns->CountInMemoryAreas() > kMaxInMemoryStorageAreas)
63         ns->PurgeMemory(DOMStorageNamespace::PURGE_AGGRESSIVE);
64     }
65   }
66   area->ExtractValues(map);
67   *send_log_get_messages = false;
68   DOMStorageNamespace* ns = GetNamespace(connection_id);
69   DCHECK(ns);
70   *send_log_get_messages = ns->IsLoggingRenderer(render_process_id_);
71   return true;
72 }
73 
GetAreaLength(int connection_id)74 unsigned DOMStorageHost::GetAreaLength(int connection_id) {
75   DOMStorageArea* area = GetOpenArea(connection_id);
76   if (!area)
77     return 0;
78   return area->Length();
79 }
80 
GetAreaKey(int connection_id,unsigned index)81 base::NullableString16 DOMStorageHost::GetAreaKey(int connection_id,
82                                                   unsigned index) {
83   DOMStorageArea* area = GetOpenArea(connection_id);
84   if (!area)
85     return base::NullableString16();
86   return area->Key(index);
87 }
88 
GetAreaItem(int connection_id,const base::string16 & key)89 base::NullableString16 DOMStorageHost::GetAreaItem(int connection_id,
90                                                    const base::string16& key) {
91   DOMStorageArea* area = GetOpenArea(connection_id);
92   if (!area)
93     return base::NullableString16();
94   return area->GetItem(key);
95 }
96 
SetAreaItem(int connection_id,const base::string16 & key,const base::string16 & value,const GURL & page_url,base::NullableString16 * old_value)97 bool DOMStorageHost::SetAreaItem(
98     int connection_id, const base::string16& key,
99     const base::string16& value, const GURL& page_url,
100     base::NullableString16* old_value) {
101   DOMStorageArea* area = GetOpenArea(connection_id);
102   if (!area)
103     return false;
104   if (!area->SetItem(key, value, old_value))
105     return false;
106   if (old_value->is_null() || old_value->string() != value)
107     context_->NotifyItemSet(area, key, value, *old_value, page_url);
108   MaybeLogTransaction(connection_id,
109                       DOMStorageNamespace::TRANSACTION_WRITE,
110                       area->origin(), page_url, key,
111                       base::NullableString16(value, false));
112   return true;
113 }
114 
LogGetAreaItem(int connection_id,const base::string16 & key,const base::NullableString16 & value)115 void DOMStorageHost::LogGetAreaItem(
116     int connection_id, const base::string16& key,
117     const base::NullableString16& value) {
118   DOMStorageArea* area = GetOpenArea(connection_id);
119   if (!area)
120     return;
121   MaybeLogTransaction(connection_id,
122                       DOMStorageNamespace::TRANSACTION_READ,
123                       area->origin(), GURL(), key, value);
124 }
125 
RemoveAreaItem(int connection_id,const base::string16 & key,const GURL & page_url,base::string16 * old_value)126 bool DOMStorageHost::RemoveAreaItem(
127     int connection_id, const base::string16& key, const GURL& page_url,
128     base::string16* old_value) {
129   DOMStorageArea* area = GetOpenArea(connection_id);
130   if (!area)
131     return false;
132   if (!area->RemoveItem(key, old_value))
133     return false;
134   context_->NotifyItemRemoved(area, key, *old_value, page_url);
135   MaybeLogTransaction(connection_id,
136                       DOMStorageNamespace::TRANSACTION_REMOVE,
137                       area->origin(), page_url, key, base::NullableString16());
138   return true;
139 }
140 
ClearArea(int connection_id,const GURL & page_url)141 bool DOMStorageHost::ClearArea(int connection_id, const GURL& page_url) {
142   DOMStorageArea* area = GetOpenArea(connection_id);
143   if (!area)
144     return false;
145   if (!area->Clear())
146     return false;
147   context_->NotifyAreaCleared(area, page_url);
148   MaybeLogTransaction(connection_id,
149                       DOMStorageNamespace::TRANSACTION_CLEAR,
150                       area->origin(), page_url, base::string16(),
151                       base::NullableString16());
152   return true;
153 }
154 
HasAreaOpen(int64 namespace_id,const GURL & origin,int64 * alias_namespace_id) const155 bool DOMStorageHost::HasAreaOpen(
156     int64 namespace_id, const GURL& origin, int64* alias_namespace_id) const {
157   AreaMap::const_iterator it = connections_.begin();
158   for (; it != connections_.end(); ++it) {
159     if (namespace_id == it->second.area_->namespace_id() &&
160         origin == it->second.area_->origin()) {
161       *alias_namespace_id = it->second.namespace_->namespace_id();
162       return true;
163     }
164   }
165   return false;
166 }
167 
ResetOpenAreasForNamespace(int64 namespace_id)168 bool DOMStorageHost::ResetOpenAreasForNamespace(int64 namespace_id) {
169   bool result = false;
170   AreaMap::iterator it = connections_.begin();
171   for (; it != connections_.end(); ++it) {
172     if (namespace_id == it->second.namespace_->namespace_id()) {
173       GURL origin = it->second.area_->origin();
174       it->second.namespace_->CloseStorageArea(it->second.area_.get());
175       it->second.area_ = it->second.namespace_->OpenStorageArea(origin);
176       result = true;
177     }
178   }
179   return result;
180 }
181 
GetOpenArea(int connection_id)182 DOMStorageArea* DOMStorageHost::GetOpenArea(int connection_id) {
183   AreaMap::iterator found = connections_.find(connection_id);
184   if (found == connections_.end())
185     return NULL;
186   return found->second.area_.get();
187 }
188 
GetNamespace(int connection_id)189 DOMStorageNamespace* DOMStorageHost::GetNamespace(int connection_id) {
190   AreaMap::iterator found = connections_.find(connection_id);
191   if (found == connections_.end())
192     return NULL;
193   return found->second.namespace_.get();
194 }
195 
MaybeLogTransaction(int connection_id,DOMStorageNamespace::LogType transaction_type,const GURL & origin,const GURL & page_url,const base::string16 & key,const base::NullableString16 & value)196 void DOMStorageHost::MaybeLogTransaction(
197     int connection_id,
198     DOMStorageNamespace::LogType transaction_type,
199     const GURL& origin,
200     const GURL& page_url,
201     const base::string16& key,
202     const base::NullableString16& value) {
203   DOMStorageNamespace* ns = GetNamespace(connection_id);
204   DCHECK(ns);
205   if (!ns->IsLoggingRenderer(render_process_id_))
206     return;
207   DOMStorageNamespace::TransactionRecord transaction;
208   transaction.transaction_type = transaction_type;
209   transaction.origin = origin;
210   transaction.page_url = page_url;
211   transaction.key = key;
212   transaction.value = value;
213   ns->AddTransaction(render_process_id_, transaction);
214 }
215 
216 // NamespaceAndArea
217 
NamespaceAndArea()218 DOMStorageHost::NamespaceAndArea::NamespaceAndArea() {}
~NamespaceAndArea()219 DOMStorageHost::NamespaceAndArea::~NamespaceAndArea() {}
220 
221 }  // namespace content
222