1 // Copyright (c) 2012 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 "webkit/browser/database/database_quota_client.h" 6 7 #include <vector> 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/location.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/message_loop/message_loop_proxy.h" 14 #include "base/task_runner_util.h" 15 #include "net/base/net_errors.h" 16 #include "net/base/net_util.h" 17 #include "webkit/browser/database/database_tracker.h" 18 #include "webkit/browser/database/database_util.h" 19 #include "webkit/common/database/database_identifier.h" 20 21 using quota::QuotaClient; 22 23 namespace webkit_database { 24 25 namespace { 26 27 int64 GetOriginUsageOnDBThread( 28 DatabaseTracker* db_tracker, 29 const GURL& origin_url) { 30 OriginInfo info; 31 if (db_tracker->GetOriginInfo( 32 webkit_database::GetIdentifierFromOrigin(origin_url), &info)) 33 return info.TotalSize(); 34 return 0; 35 } 36 37 void GetOriginsOnDBThread( 38 DatabaseTracker* db_tracker, 39 std::set<GURL>* origins_ptr) { 40 std::vector<std::string> origin_identifiers; 41 if (db_tracker->GetAllOriginIdentifiers(&origin_identifiers)) { 42 for (std::vector<std::string>::const_iterator iter = 43 origin_identifiers.begin(); 44 iter != origin_identifiers.end(); ++iter) { 45 GURL origin = webkit_database::GetOriginFromIdentifier(*iter); 46 origins_ptr->insert(origin); 47 } 48 } 49 } 50 51 void GetOriginsForHostOnDBThread( 52 DatabaseTracker* db_tracker, 53 std::set<GURL>* origins_ptr, 54 const std::string& host) { 55 std::vector<std::string> origin_identifiers; 56 if (db_tracker->GetAllOriginIdentifiers(&origin_identifiers)) { 57 for (std::vector<std::string>::const_iterator iter = 58 origin_identifiers.begin(); 59 iter != origin_identifiers.end(); ++iter) { 60 GURL origin = webkit_database::GetOriginFromIdentifier(*iter); 61 if (host == net::GetHostOrSpecFromURL(origin)) 62 origins_ptr->insert(origin); 63 } 64 } 65 } 66 67 void DidGetOrigins( 68 const QuotaClient::GetOriginsCallback& callback, 69 std::set<GURL>* origins_ptr) { 70 callback.Run(*origins_ptr); 71 } 72 73 void DidDeleteOriginData( 74 base::SingleThreadTaskRunner* original_task_runner, 75 const QuotaClient::DeletionCallback& callback, 76 int result) { 77 if (result == net::ERR_IO_PENDING) { 78 // The callback will be invoked via 79 // DatabaseTracker::ScheduleDatabasesForDeletion. 80 return; 81 } 82 83 quota::QuotaStatusCode status; 84 if (result == net::OK) 85 status = quota::kQuotaStatusOk; 86 else 87 status = quota::kQuotaStatusUnknown; 88 89 if (original_task_runner->BelongsToCurrentThread()) 90 callback.Run(status); 91 else 92 original_task_runner->PostTask(FROM_HERE, base::Bind(callback, status)); 93 } 94 95 } // namespace 96 97 DatabaseQuotaClient::DatabaseQuotaClient( 98 base::MessageLoopProxy* db_tracker_thread, 99 DatabaseTracker* db_tracker) 100 : db_tracker_thread_(db_tracker_thread), db_tracker_(db_tracker) { 101 } 102 103 DatabaseQuotaClient::~DatabaseQuotaClient() { 104 if (db_tracker_thread_.get() && 105 !db_tracker_thread_->RunsTasksOnCurrentThread() && db_tracker_.get()) { 106 DatabaseTracker* tracker = db_tracker_.get(); 107 tracker->AddRef(); 108 db_tracker_ = NULL; 109 if (!db_tracker_thread_->ReleaseSoon(FROM_HERE, tracker)) 110 tracker->Release(); 111 } 112 } 113 114 QuotaClient::ID DatabaseQuotaClient::id() const { 115 return kDatabase; 116 } 117 118 void DatabaseQuotaClient::OnQuotaManagerDestroyed() { 119 delete this; 120 } 121 122 void DatabaseQuotaClient::GetOriginUsage( 123 const GURL& origin_url, 124 quota::StorageType type, 125 const GetUsageCallback& callback) { 126 DCHECK(!callback.is_null()); 127 DCHECK(db_tracker_.get()); 128 129 // All databases are in the temp namespace for now. 130 if (type != quota::kStorageTypeTemporary) { 131 callback.Run(0); 132 return; 133 } 134 135 base::PostTaskAndReplyWithResult( 136 db_tracker_thread_.get(), 137 FROM_HERE, 138 base::Bind(&GetOriginUsageOnDBThread, db_tracker_, origin_url), 139 callback); 140 } 141 142 void DatabaseQuotaClient::GetOriginsForType( 143 quota::StorageType type, 144 const GetOriginsCallback& callback) { 145 DCHECK(!callback.is_null()); 146 DCHECK(db_tracker_.get()); 147 148 // All databases are in the temp namespace for now. 149 if (type != quota::kStorageTypeTemporary) { 150 callback.Run(std::set<GURL>()); 151 return; 152 } 153 154 std::set<GURL>* origins_ptr = new std::set<GURL>(); 155 db_tracker_thread_->PostTaskAndReply( 156 FROM_HERE, 157 base::Bind(&GetOriginsOnDBThread, 158 db_tracker_, 159 base::Unretained(origins_ptr)), 160 base::Bind(&DidGetOrigins, 161 callback, 162 base::Owned(origins_ptr))); 163 } 164 165 void DatabaseQuotaClient::GetOriginsForHost( 166 quota::StorageType type, 167 const std::string& host, 168 const GetOriginsCallback& callback) { 169 DCHECK(!callback.is_null()); 170 DCHECK(db_tracker_.get()); 171 172 // All databases are in the temp namespace for now. 173 if (type != quota::kStorageTypeTemporary) { 174 callback.Run(std::set<GURL>()); 175 return; 176 } 177 178 std::set<GURL>* origins_ptr = new std::set<GURL>(); 179 db_tracker_thread_->PostTaskAndReply( 180 FROM_HERE, 181 base::Bind(&GetOriginsForHostOnDBThread, 182 db_tracker_, 183 base::Unretained(origins_ptr), 184 host), 185 base::Bind(&DidGetOrigins, 186 callback, 187 base::Owned(origins_ptr))); 188 } 189 190 void DatabaseQuotaClient::DeleteOriginData( 191 const GURL& origin, 192 quota::StorageType type, 193 const DeletionCallback& callback) { 194 DCHECK(!callback.is_null()); 195 DCHECK(db_tracker_.get()); 196 197 // All databases are in the temp namespace for now, so nothing to delete. 198 if (type != quota::kStorageTypeTemporary) { 199 callback.Run(quota::kQuotaStatusOk); 200 return; 201 } 202 203 base::Callback<void(int)> delete_callback = 204 base::Bind(&DidDeleteOriginData, 205 base::MessageLoopProxy::current(), 206 callback); 207 208 PostTaskAndReplyWithResult( 209 db_tracker_thread_.get(), 210 FROM_HERE, 211 base::Bind(&DatabaseTracker::DeleteDataForOrigin, 212 db_tracker_, 213 webkit_database::GetIdentifierFromOrigin(origin), 214 delete_callback), 215 delete_callback); 216 } 217 218 bool DatabaseQuotaClient::DoesSupport(quota::StorageType type) const { 219 return type == quota::kStorageTypeTemporary; 220 } 221 222 } // namespace webkit_database 223