OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/in_process_webkit/indexed_db_context_impl.h" | 5 #include "content/browser/in_process_webkit/indexed_db_context_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 quota_manager_proxy_(quota_manager_proxy) { | 99 quota_manager_proxy_(quota_manager_proxy) { |
100 if (!data_path.empty()) | 100 if (!data_path.empty()) |
101 data_path_ = data_path.Append(kIndexedDBDirectory); | 101 data_path_ = data_path.Append(kIndexedDBDirectory); |
102 if (quota_manager_proxy && | 102 if (quota_manager_proxy && |
103 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) { | 103 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) { |
104 quota_manager_proxy->RegisterClient( | 104 quota_manager_proxy->RegisterClient( |
105 new IndexedDBQuotaClient(webkit_thread_loop, this)); | 105 new IndexedDBQuotaClient(webkit_thread_loop, this)); |
106 } | 106 } |
107 } | 107 } |
108 | 108 |
109 IndexedDBContextImpl::~IndexedDBContextImpl() { | |
110 WebKit::WebIDBFactory* factory = idb_factory_.release(); | |
111 if (factory) { | |
112 if (!BrowserThread::DeleteSoon(BrowserThread::WEBKIT_DEPRECATED, | |
113 FROM_HERE, factory)) | |
114 delete factory; | |
115 } | |
116 | |
117 if (data_path_.empty()) | |
118 return; | |
119 | |
120 if (save_session_state_) | |
121 return; | |
122 | |
123 bool has_session_only_databases = | |
124 special_storage_policy_.get() && | |
125 special_storage_policy_->HasSessionOnlyOrigins(); | |
126 | |
127 // Clearning only session-only databases, and there are none. | |
128 if (!clear_local_state_on_exit_ && !has_session_only_databases) | |
129 return; | |
130 | |
131 // No WEBKIT thread here means we are running in a unit test where no clean | |
132 // up is needed. | |
133 BrowserThread::PostTask( | |
134 BrowserThread::WEBKIT_DEPRECATED, FROM_HERE, | |
135 base::Bind(&ClearLocalState, data_path_, clear_local_state_on_exit_, | |
136 special_storage_policy_)); | |
137 } | |
138 | |
139 WebIDBFactory* IndexedDBContextImpl::GetIDBFactory() { | 109 WebIDBFactory* IndexedDBContextImpl::GetIDBFactory() { |
140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); | 110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); |
141 if (!idb_factory_.get()) { | 111 if (!idb_factory_.get()) { |
142 // Prime our cache of origins with existing databases so we can | 112 // Prime our cache of origins with existing databases so we can |
143 // detect when dbs are newly created. | 113 // detect when dbs are newly created. |
144 GetOriginSet(); | 114 GetOriginSet(); |
145 idb_factory_.reset(WebIDBFactory::create()); | 115 idb_factory_.reset(WebIDBFactory::create()); |
146 } | 116 } |
147 return idb_factory_.get(); | 117 return idb_factory_.get(); |
148 } | 118 } |
149 | 119 |
150 void IndexedDBContextImpl::DeleteForOrigin(const GURL& origin_url) { | |
151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); | |
152 if (data_path_.empty() || !IsInOriginSet(origin_url)) | |
153 return; | |
154 // TODO(michaeln): When asked to delete an origin with open connections, | |
155 // forcibly close those connections then delete. | |
156 if (connection_count_.find(origin_url) == connection_count_.end()) { | |
157 string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url); | |
158 FilePath idb_directory = GetIndexedDBFilePath(origin_id); | |
159 EnsureDiskUsageCacheInitialized(origin_url); | |
160 bool deleted = file_util::Delete(idb_directory, true /*recursive*/); | |
161 QueryDiskAndUpdateQuotaUsage(origin_url); | |
162 if (deleted) { | |
163 RemoveFromOriginSet(origin_url); | |
164 origin_size_map_.erase(origin_url); | |
165 space_available_map_.erase(origin_url); | |
166 } | |
167 } | |
168 } | |
169 | |
170 FilePath IndexedDBContextImpl::GetFilePathForTesting( | |
171 const string16& origin_id) const { | |
172 return GetIndexedDBFilePath(origin_id); | |
173 } | |
174 | |
175 std::vector<GURL> IndexedDBContextImpl::GetAllOrigins() { | 120 std::vector<GURL> IndexedDBContextImpl::GetAllOrigins() { |
176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); | 121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); |
177 std::vector<GURL> origins; | 122 std::vector<GURL> origins; |
178 std::set<GURL>* origins_set = GetOriginSet(); | 123 std::set<GURL>* origins_set = GetOriginSet(); |
179 for (std::set<GURL>::const_iterator iter = origins_set->begin(); | 124 for (std::set<GURL>::const_iterator iter = origins_set->begin(); |
180 iter != origins_set->end(); ++iter) { | 125 iter != origins_set->end(); ++iter) { |
181 origins.push_back(*iter); | 126 origins.push_back(*iter); |
182 } | 127 } |
183 return origins; | 128 return origins; |
184 } | 129 } |
185 | 130 |
186 int64 IndexedDBContextImpl::GetOriginDiskUsage(const GURL& origin_url) { | 131 int64 IndexedDBContextImpl::GetOriginDiskUsage(const GURL& origin_url) { |
187 if (data_path_.empty() || !IsInOriginSet(origin_url)) | 132 if (data_path_.empty() || !IsInOriginSet(origin_url)) |
188 return 0; | 133 return 0; |
189 EnsureDiskUsageCacheInitialized(origin_url); | 134 EnsureDiskUsageCacheInitialized(origin_url); |
190 return origin_size_map_[origin_url]; | 135 return origin_size_map_[origin_url]; |
191 } | 136 } |
192 | 137 |
193 base::Time IndexedDBContextImpl::GetOriginLastModified(const GURL& origin_url) { | 138 base::Time IndexedDBContextImpl::GetOriginLastModified(const GURL& origin_url) { |
194 if (data_path_.empty() || !IsInOriginSet(origin_url)) | 139 if (data_path_.empty() || !IsInOriginSet(origin_url)) |
195 return base::Time(); | 140 return base::Time(); |
196 string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url); | 141 string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url); |
197 FilePath idb_directory = GetIndexedDBFilePath(origin_id); | 142 FilePath idb_directory = GetIndexedDBFilePath(origin_id); |
198 base::PlatformFileInfo file_info; | 143 base::PlatformFileInfo file_info; |
199 if (!file_util::GetFileInfo(idb_directory, &file_info)) | 144 if (!file_util::GetFileInfo(idb_directory, &file_info)) |
200 return base::Time(); | 145 return base::Time(); |
201 return file_info.last_modified; | 146 return file_info.last_modified; |
202 } | 147 } |
203 | 148 |
| 149 void IndexedDBContextImpl::DeleteForOrigin(const GURL& origin_url) { |
| 150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); |
| 151 if (data_path_.empty() || !IsInOriginSet(origin_url)) |
| 152 return; |
| 153 // TODO(michaeln): When asked to delete an origin with open connections, |
| 154 // forcibly close those connections then delete. |
| 155 if (connection_count_.find(origin_url) == connection_count_.end()) { |
| 156 string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url); |
| 157 FilePath idb_directory = GetIndexedDBFilePath(origin_id); |
| 158 EnsureDiskUsageCacheInitialized(origin_url); |
| 159 bool deleted = file_util::Delete(idb_directory, true /*recursive*/); |
| 160 QueryDiskAndUpdateQuotaUsage(origin_url); |
| 161 if (deleted) { |
| 162 RemoveFromOriginSet(origin_url); |
| 163 origin_size_map_.erase(origin_url); |
| 164 space_available_map_.erase(origin_url); |
| 165 } |
| 166 } |
| 167 } |
| 168 |
| 169 FilePath IndexedDBContextImpl::GetFilePathForTesting( |
| 170 const string16& origin_id) const { |
| 171 return GetIndexedDBFilePath(origin_id); |
| 172 } |
| 173 |
204 void IndexedDBContextImpl::ConnectionOpened(const GURL& origin_url) { | 174 void IndexedDBContextImpl::ConnectionOpened(const GURL& origin_url) { |
205 if (quota_manager_proxy()) { | 175 if (quota_manager_proxy()) { |
206 quota_manager_proxy()->NotifyStorageAccessed( | 176 quota_manager_proxy()->NotifyStorageAccessed( |
207 quota::QuotaClient::kIndexedDatabase, origin_url, | 177 quota::QuotaClient::kIndexedDatabase, origin_url, |
208 quota::kStorageTypeTemporary); | 178 quota::kStorageTypeTemporary); |
209 } | 179 } |
210 connection_count_[origin_url]++; | 180 connection_count_[origin_url]++; |
211 if (AddToOriginSet(origin_url)) { | 181 if (AddToOriginSet(origin_url)) { |
212 // A newly created db, notify the quota system. | 182 // A newly created db, notify the quota system. |
213 QueryDiskAndUpdateQuotaUsage(origin_url); | 183 QueryDiskAndUpdateQuotaUsage(origin_url); |
(...skipping 16 matching lines...) Expand all Loading... |
230 connection_count_.erase(origin_url); | 200 connection_count_.erase(origin_url); |
231 } | 201 } |
232 } | 202 } |
233 | 203 |
234 void IndexedDBContextImpl::TransactionComplete(const GURL& origin_url) { | 204 void IndexedDBContextImpl::TransactionComplete(const GURL& origin_url) { |
235 DCHECK(connection_count_[origin_url] > 0); | 205 DCHECK(connection_count_[origin_url] > 0); |
236 QueryDiskAndUpdateQuotaUsage(origin_url); | 206 QueryDiskAndUpdateQuotaUsage(origin_url); |
237 QueryAvailableQuota(origin_url); | 207 QueryAvailableQuota(origin_url); |
238 } | 208 } |
239 | 209 |
240 FilePath IndexedDBContextImpl::GetIndexedDBFilePath( | |
241 const string16& origin_id) const { | |
242 DCHECK(!data_path_.empty()); | |
243 FilePath::StringType id = | |
244 webkit_glue::WebStringToFilePathString(origin_id).append( | |
245 FILE_PATH_LITERAL(".indexeddb")); | |
246 return data_path_.Append(id.append(kIndexedDBExtension)); | |
247 } | |
248 | |
249 bool IndexedDBContextImpl::WouldBeOverQuota(const GURL& origin_url, | 210 bool IndexedDBContextImpl::WouldBeOverQuota(const GURL& origin_url, |
250 int64 additional_bytes) { | 211 int64 additional_bytes) { |
251 if (space_available_map_.find(origin_url) == space_available_map_.end()) { | 212 if (space_available_map_.find(origin_url) == space_available_map_.end()) { |
252 // We haven't heard back from the QuotaManager yet, just let it through. | 213 // We haven't heard back from the QuotaManager yet, just let it through. |
253 return false; | 214 return false; |
254 } | 215 } |
255 bool over_quota = additional_bytes > space_available_map_[origin_url]; | 216 bool over_quota = additional_bytes > space_available_map_[origin_url]; |
256 return over_quota; | 217 return over_quota; |
257 } | 218 } |
258 | 219 |
259 bool IndexedDBContextImpl::IsOverQuota(const GURL& origin_url) { | 220 bool IndexedDBContextImpl::IsOverQuota(const GURL& origin_url) { |
260 const int kOneAdditionalByte = 1; | 221 const int kOneAdditionalByte = 1; |
261 return WouldBeOverQuota(origin_url, kOneAdditionalByte); | 222 return WouldBeOverQuota(origin_url, kOneAdditionalByte); |
262 } | 223 } |
263 | 224 |
264 quota::QuotaManagerProxy* IndexedDBContextImpl::quota_manager_proxy() { | 225 quota::QuotaManagerProxy* IndexedDBContextImpl::quota_manager_proxy() { |
265 return quota_manager_proxy_; | 226 return quota_manager_proxy_; |
266 } | 227 } |
267 | 228 |
| 229 IndexedDBContextImpl::~IndexedDBContextImpl() { |
| 230 WebKit::WebIDBFactory* factory = idb_factory_.release(); |
| 231 if (factory) { |
| 232 if (!BrowserThread::DeleteSoon(BrowserThread::WEBKIT_DEPRECATED, |
| 233 FROM_HERE, factory)) |
| 234 delete factory; |
| 235 } |
| 236 |
| 237 if (data_path_.empty()) |
| 238 return; |
| 239 |
| 240 if (save_session_state_) |
| 241 return; |
| 242 |
| 243 bool has_session_only_databases = |
| 244 special_storage_policy_.get() && |
| 245 special_storage_policy_->HasSessionOnlyOrigins(); |
| 246 |
| 247 // Clearning only session-only databases, and there are none. |
| 248 if (!clear_local_state_on_exit_ && !has_session_only_databases) |
| 249 return; |
| 250 |
| 251 // No WEBKIT thread here means we are running in a unit test where no clean |
| 252 // up is needed. |
| 253 BrowserThread::PostTask( |
| 254 BrowserThread::WEBKIT_DEPRECATED, FROM_HERE, |
| 255 base::Bind(&ClearLocalState, data_path_, clear_local_state_on_exit_, |
| 256 special_storage_policy_)); |
| 257 } |
| 258 |
| 259 FilePath IndexedDBContextImpl::GetIndexedDBFilePath( |
| 260 const string16& origin_id) const { |
| 261 DCHECK(!data_path_.empty()); |
| 262 FilePath::StringType id = |
| 263 webkit_glue::WebStringToFilePathString(origin_id).append( |
| 264 FILE_PATH_LITERAL(".indexeddb")); |
| 265 return data_path_.Append(id.append(kIndexedDBExtension)); |
| 266 } |
| 267 |
268 int64 IndexedDBContextImpl::ReadUsageFromDisk(const GURL& origin_url) const { | 268 int64 IndexedDBContextImpl::ReadUsageFromDisk(const GURL& origin_url) const { |
269 if (data_path_.empty()) | 269 if (data_path_.empty()) |
270 return 0; | 270 return 0; |
271 string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url); | 271 string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url); |
272 FilePath file_path = GetIndexedDBFilePath(origin_id); | 272 FilePath file_path = GetIndexedDBFilePath(origin_id); |
273 return file_util::ComputeDirectorySize(file_path); | 273 return file_util::ComputeDirectorySize(file_path); |
274 } | 274 } |
275 | 275 |
276 void IndexedDBContextImpl::EnsureDiskUsageCacheInitialized( | 276 void IndexedDBContextImpl::EnsureDiskUsageCacheInitialized( |
277 const GURL& origin_url) { | 277 const GURL& origin_url) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 } | 348 } |
349 } | 349 } |
350 return origin_set_.get(); | 350 return origin_set_.get(); |
351 } | 351 } |
352 | 352 |
353 void IndexedDBContextImpl::ResetCaches() { | 353 void IndexedDBContextImpl::ResetCaches() { |
354 origin_set_.reset(); | 354 origin_set_.reset(); |
355 origin_size_map_.clear(); | 355 origin_size_map_.clear(); |
356 space_available_map_.clear(); | 356 space_available_map_.clear(); |
357 } | 357 } |
OLD | NEW |