| 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 |