OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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/browser/dom_storage/dom_storage_namespace.h" | 5 #include "content/browser/dom_storage/dom_storage_namespace.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/sys_info.h" | |
10 #include "content/browser/dom_storage/dom_storage_area.h" | 11 #include "content/browser/dom_storage/dom_storage_area.h" |
11 #include "content/browser/dom_storage/dom_storage_task_runner.h" | 12 #include "content/browser/dom_storage/dom_storage_task_runner.h" |
12 #include "content/browser/dom_storage/session_storage_database.h" | 13 #include "content/browser/dom_storage/session_storage_database.h" |
13 #include "content/common/dom_storage/dom_storage_types.h" | 14 #include "content/common/dom_storage/dom_storage_types.h" |
14 | 15 |
15 namespace content { | 16 namespace content { |
17 namespace { | |
18 // Limits on the cache size and number of areas in memory, over which the areas | |
19 // are purged. | |
20 #if defined(OS_ANDROID) | |
21 const size_t kMaxStorageAreaCount = 20; | |
22 const uint64_t kMaxCacheSize = 2 * 1024 * 1024; | |
23 #else | |
24 const size_t kMaxStorageAreaCount = 100; | |
25 const uint64_t kMaxCacheSize = 20 * 1024 * 1024; | |
26 #endif | |
ssid
2016/05/10 02:04:16
Not sure if I should move these to dom_storage_typ
| |
27 } // namespace | |
16 | 28 |
17 DOMStorageNamespace::DOMStorageNamespace( | 29 DOMStorageNamespace::DOMStorageNamespace( |
18 const base::FilePath& directory, | 30 const base::FilePath& directory, |
19 DOMStorageTaskRunner* task_runner) | 31 DOMStorageTaskRunner* task_runner) |
20 : namespace_id_(kLocalStorageNamespaceId), | 32 : namespace_id_(kLocalStorageNamespaceId), |
21 directory_(directory), | 33 directory_(directory), |
22 task_runner_(task_runner) { | 34 task_runner_(task_runner) { |
23 } | 35 } |
24 | 36 |
25 DOMStorageNamespace::DOMStorageNamespace( | 37 DOMStorageNamespace::DOMStorageNamespace( |
26 int64_t namespace_id, | 38 int64_t namespace_id, |
27 const std::string& persistent_namespace_id, | 39 const std::string& persistent_namespace_id, |
28 SessionStorageDatabase* session_storage_database, | 40 SessionStorageDatabase* session_storage_database, |
29 DOMStorageTaskRunner* task_runner) | 41 DOMStorageTaskRunner* task_runner) |
30 : namespace_id_(namespace_id), | 42 : namespace_id_(namespace_id), |
31 persistent_namespace_id_(persistent_namespace_id), | 43 persistent_namespace_id_(persistent_namespace_id), |
32 task_runner_(task_runner), | 44 task_runner_(task_runner), |
33 session_storage_database_(session_storage_database) { | 45 session_storage_database_(session_storage_database), |
46 is_low_end_device_(base::SysInfo::IsLowEndDevice()) { | |
34 DCHECK_NE(kLocalStorageNamespaceId, namespace_id); | 47 DCHECK_NE(kLocalStorageNamespaceId, namespace_id); |
35 } | 48 } |
36 | 49 |
37 DOMStorageNamespace::~DOMStorageNamespace() { | 50 DOMStorageNamespace::~DOMStorageNamespace() { |
38 } | 51 } |
39 | 52 |
40 DOMStorageArea* DOMStorageNamespace::OpenStorageArea(const GURL& origin) { | 53 DOMStorageArea* DOMStorageNamespace::OpenStorageArea(const GURL& origin) { |
41 if (AreaHolder* holder = GetAreaHolder(origin)) { | 54 if (AreaHolder* holder = GetAreaHolder(origin)) { |
42 ++(holder->open_count_); | 55 ++(holder->open_count_); |
43 return holder->area_.get(); | 56 return holder->area_.get(); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
113 | 126 |
114 void DOMStorageNamespace::DeleteSessionStorageOrigin(const GURL& origin) { | 127 void DOMStorageNamespace::DeleteSessionStorageOrigin(const GURL& origin) { |
115 DOMStorageArea* area = OpenStorageArea(origin); | 128 DOMStorageArea* area = OpenStorageArea(origin); |
116 area->FastClear(); | 129 area->FastClear(); |
117 CloseStorageArea(area); | 130 CloseStorageArea(area); |
118 } | 131 } |
119 | 132 |
120 void DOMStorageNamespace::PurgeMemory(PurgeOption option) { | 133 void DOMStorageNamespace::PurgeMemory(PurgeOption option) { |
121 if (directory_.empty()) | 134 if (directory_.empty()) |
122 return; // We can't purge w/o backing on disk. | 135 return; // We can't purge w/o backing on disk. |
136 | |
137 if (option == PURGE_IF_NEEDED) { | |
138 if (!ShouldPurgeMemory()) | |
139 return; | |
140 option = PURGE_UNOPENED; | |
141 } | |
142 | |
123 AreaMap::iterator it = areas_.begin(); | 143 AreaMap::iterator it = areas_.begin(); |
124 while (it != areas_.end()) { | 144 while (it != areas_.end()) { |
125 const AreaHolder& holder = it->second; | 145 const AreaHolder& holder = it->second; |
126 | 146 |
127 // We can't purge if there are changes pending. | 147 // We can't purge if there are changes pending. |
128 if (holder.area_->HasUncommittedChanges()) { | 148 if (holder.area_->HasUncommittedChanges()) { |
129 if (holder.open_count_ == 0) { | 149 if (holder.open_count_ == 0) { |
130 // Schedule an immediate commit so the next time we're asked to purge, | 150 // Schedule an immediate commit so the next time we're asked to purge, |
131 // we can drop it from memory. | 151 // we can drop it from memory. |
132 holder.area_->ScheduleImmediateCommit(); | 152 holder.area_->ScheduleImmediateCommit(); |
133 } | 153 } |
134 ++it; | 154 it++; |
135 continue; | 155 continue; |
136 } | 156 } |
137 | 157 |
138 // If not in use, we can shut it down and remove | 158 // If not in use, we can shut it down and remove |
139 // it from our collection entirely. | 159 // it from our collection entirely. |
140 if (holder.open_count_ == 0) { | 160 if (holder.open_count_ == 0) { |
141 holder.area_->Shutdown(); | 161 holder.area_->Shutdown(); |
142 areas_.erase(it++); | 162 areas_.erase(it++); |
143 continue; | 163 continue; |
144 } | 164 } |
145 | 165 |
146 if (option == PURGE_AGGRESSIVE) { | 166 if (option == PURGE_AGGRESSIVE) { |
147 // If aggressive is true, we clear caches and such | 167 // If aggressive is true, we clear caches and such |
148 // for opened areas. | 168 // for opened areas. |
149 holder.area_->PurgeMemory(); | 169 holder.area_->PurgeMemory(); |
150 } | 170 } |
151 | 171 it++; |
152 ++it; | |
153 } | 172 } |
154 } | 173 } |
155 | 174 |
175 bool DOMStorageNamespace::ShouldPurgeMemory() { | |
176 // Purging is done based on the cache sizes without including the database | |
177 // size since it can be expensive trying to estimate the sqlite usage for all | |
178 // databases. | |
179 size_t total_cache_size = 0; | |
180 size_t total_area_count = 0; | |
181 unsigned inactive_area_count = 0; | |
182 for (AreaMap::const_iterator it = areas_.begin(); it != areas_.end(); ++it) { | |
183 if (it->second.area_->IsLoadedInMemory()) { | |
184 total_cache_size += it->second.area_->map_usage_in_bytes(); | |
185 ++total_area_count; | |
186 if (it->second.open_count_ == 0) | |
187 ++inactive_area_count; | |
188 } | |
189 } | |
190 | |
191 // Purge caches of closed databases on low end devices. | |
192 if (is_low_end_device_ && inactive_area_count) | |
193 return true; | |
194 | |
195 if (total_cache_size > kMaxCacheSize || | |
196 total_area_count > kMaxStorageAreaCount) | |
197 return true; | |
198 | |
199 return false; | |
200 } | |
201 | |
156 void DOMStorageNamespace::Shutdown() { | 202 void DOMStorageNamespace::Shutdown() { |
157 AreaMap::const_iterator it = areas_.begin(); | 203 AreaMap::const_iterator it = areas_.begin(); |
158 for (; it != areas_.end(); ++it) | 204 for (; it != areas_.end(); ++it) |
159 it->second.area_->Shutdown(); | 205 it->second.area_->Shutdown(); |
160 } | 206 } |
161 | 207 |
162 void DOMStorageNamespace::Flush() { | 208 void DOMStorageNamespace::Flush() { |
163 for (auto& entry : areas_) { | 209 for (auto& entry : areas_) { |
164 if (!entry.second.area_->HasUncommittedChanges()) | 210 if (!entry.second.area_->HasUncommittedChanges()) |
165 continue; | 211 continue; |
166 entry.second.area_->ScheduleImmediateCommit(); | 212 entry.second.area_->ScheduleImmediateCommit(); |
167 } | 213 } |
168 } | 214 } |
169 | 215 |
170 unsigned int DOMStorageNamespace::CountInMemoryAreas() const { | |
171 unsigned int area_count = 0; | |
172 for (AreaMap::const_iterator it = areas_.begin(); it != areas_.end(); ++it) { | |
173 if (it->second.area_->IsLoadedInMemory()) | |
174 ++area_count; | |
175 } | |
176 return area_count; | |
177 } | |
178 | |
179 void DOMStorageNamespace::OnMemoryDump( | 216 void DOMStorageNamespace::OnMemoryDump( |
180 base::trace_event::ProcessMemoryDump* pmd) { | 217 base::trace_event::ProcessMemoryDump* pmd) { |
181 DCHECK(task_runner_->IsRunningOnPrimarySequence()); | 218 DCHECK(task_runner_->IsRunningOnPrimarySequence()); |
182 for (const auto& it : areas_) | 219 for (const auto& it : areas_) |
183 it.second.area_->OnMemoryDump(pmd); | 220 it.second.area_->OnMemoryDump(pmd); |
184 } | 221 } |
185 | 222 |
186 void DOMStorageNamespace::GetOriginsWithAreas( | 223 void DOMStorageNamespace::GetOriginsWithAreas( |
187 std::vector<GURL>* origins) const { | 224 std::vector<GURL>* origins) const { |
188 origins->clear(); | 225 origins->clear(); |
(...skipping 19 matching lines...) Expand all Loading... | |
208 DOMStorageArea* area, int count) | 245 DOMStorageArea* area, int count) |
209 : area_(area), open_count_(count) { | 246 : area_(area), open_count_(count) { |
210 } | 247 } |
211 | 248 |
212 DOMStorageNamespace::AreaHolder::AreaHolder(const AreaHolder& other) = default; | 249 DOMStorageNamespace::AreaHolder::AreaHolder(const AreaHolder& other) = default; |
213 | 250 |
214 DOMStorageNamespace::AreaHolder::~AreaHolder() { | 251 DOMStorageNamespace::AreaHolder::~AreaHolder() { |
215 } | 252 } |
216 | 253 |
217 } // namespace content | 254 } // namespace content |
OLD | NEW |