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 "chrome/browser/browsing_data/browsing_data_database_helper.h" 6 7 #include "base/bind.h" 8 #include "base/callback.h" 9 #include "base/file_util.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "chrome/browser/browsing_data/browsing_data_helper.h" 12 #include "chrome/browser/profiles/profile.h" 13 #include "content/public/browser/browser_thread.h" 14 #include "content/public/browser/storage_partition.h" 15 #include "net/base/completion_callback.h" 16 #include "net/base/net_errors.h" 17 #include "webkit/common/database/database_identifier.h" 18 19 using content::BrowserContext; 20 using content::BrowserThread; 21 using webkit_database::DatabaseIdentifier; 22 23 BrowsingDataDatabaseHelper::DatabaseInfo::DatabaseInfo( 24 const DatabaseIdentifier& identifier, 25 const std::string& database_name, 26 const std::string& description, 27 int64 size, 28 base::Time last_modified) 29 : identifier(identifier), 30 database_name(database_name), 31 description(description), 32 size(size), 33 last_modified(last_modified) { 34 } 35 36 BrowsingDataDatabaseHelper::DatabaseInfo::~DatabaseInfo() {} 37 38 BrowsingDataDatabaseHelper::BrowsingDataDatabaseHelper(Profile* profile) 39 : is_fetching_(false), 40 tracker_(BrowserContext:: 41 GetDefaultStoragePartition(profile)->GetDatabaseTracker()) { 42 } 43 44 BrowsingDataDatabaseHelper::~BrowsingDataDatabaseHelper() { 45 } 46 47 void BrowsingDataDatabaseHelper::StartFetching( 48 const base::Callback<void(const std::list<DatabaseInfo>&)>& callback) { 49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 50 DCHECK(!is_fetching_); 51 DCHECK_EQ(false, callback.is_null()); 52 53 is_fetching_ = true; 54 database_info_.clear(); 55 completion_callback_ = callback; 56 BrowserThread::PostTask( 57 BrowserThread::FILE, FROM_HERE, 58 base::Bind(&BrowsingDataDatabaseHelper::FetchDatabaseInfoOnFileThread, 59 this)); 60 } 61 62 void BrowsingDataDatabaseHelper::DeleteDatabase(const std::string& origin, 63 const std::string& name) { 64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 65 BrowserThread::PostTask( 66 BrowserThread::FILE, FROM_HERE, 67 base::Bind(&BrowsingDataDatabaseHelper::DeleteDatabaseOnFileThread, this, 68 origin, name)); 69 } 70 71 void BrowsingDataDatabaseHelper::FetchDatabaseInfoOnFileThread() { 72 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 73 std::vector<webkit_database::OriginInfo> origins_info; 74 if (tracker_.get() && tracker_->GetAllOriginsInfo(&origins_info)) { 75 for (std::vector<webkit_database::OriginInfo>::const_iterator ori = 76 origins_info.begin(); ori != origins_info.end(); ++ori) { 77 DatabaseIdentifier identifier = 78 DatabaseIdentifier::Parse(ori->GetOriginIdentifier()); 79 if (!BrowsingDataHelper::HasWebScheme(identifier.ToOrigin())) { 80 // Non-websafe state is not considered browsing data. 81 continue; 82 } 83 std::vector<base::string16> databases; 84 ori->GetAllDatabaseNames(&databases); 85 for (std::vector<base::string16>::const_iterator db = databases.begin(); 86 db != databases.end(); ++db) { 87 base::FilePath file_path = 88 tracker_->GetFullDBFilePath(ori->GetOriginIdentifier(), *db); 89 base::File::Info file_info; 90 if (base::GetFileInfo(file_path, &file_info)) { 91 database_info_.push_back(DatabaseInfo( 92 identifier, 93 base::UTF16ToUTF8(*db), 94 base::UTF16ToUTF8(ori->GetDatabaseDescription(*db)), 95 file_info.size, 96 file_info.last_modified)); 97 } 98 } 99 } 100 } 101 102 BrowserThread::PostTask( 103 BrowserThread::UI, FROM_HERE, 104 base::Bind(&BrowsingDataDatabaseHelper::NotifyInUIThread, this)); 105 } 106 107 void BrowsingDataDatabaseHelper::NotifyInUIThread() { 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 109 DCHECK(is_fetching_); 110 completion_callback_.Run(database_info_); 111 completion_callback_.Reset(); 112 is_fetching_ = false; 113 database_info_.clear(); 114 } 115 116 void BrowsingDataDatabaseHelper::DeleteDatabaseOnFileThread( 117 const std::string& origin, 118 const std::string& name) { 119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 120 if (!tracker_.get()) 121 return; 122 tracker_->DeleteDatabase(origin, base::UTF8ToUTF16(name), 123 net::CompletionCallback()); 124 } 125 126 CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::PendingDatabaseInfo( 127 const GURL& origin, 128 const std::string& name, 129 const std::string& description) 130 : origin(origin), 131 name(name), 132 description(description) { 133 } 134 135 CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::~PendingDatabaseInfo() {} 136 137 bool CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::operator<( 138 const PendingDatabaseInfo& other) const { 139 if (origin == other.origin) 140 return name < other.name; 141 return origin < other.origin; 142 } 143 144 CannedBrowsingDataDatabaseHelper::CannedBrowsingDataDatabaseHelper( 145 Profile* profile) 146 : BrowsingDataDatabaseHelper(profile), 147 profile_(profile) { 148 } 149 150 CannedBrowsingDataDatabaseHelper* CannedBrowsingDataDatabaseHelper::Clone() { 151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 152 CannedBrowsingDataDatabaseHelper* clone = 153 new CannedBrowsingDataDatabaseHelper(profile_); 154 155 clone->pending_database_info_ = pending_database_info_; 156 return clone; 157 } 158 159 void CannedBrowsingDataDatabaseHelper::AddDatabase( 160 const GURL& origin, 161 const std::string& name, 162 const std::string& description) { 163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 164 if (BrowsingDataHelper::HasWebScheme(origin)) { 165 pending_database_info_.insert(PendingDatabaseInfo( 166 origin, name, description)); 167 } 168 } 169 170 void CannedBrowsingDataDatabaseHelper::Reset() { 171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 172 pending_database_info_.clear(); 173 } 174 175 bool CannedBrowsingDataDatabaseHelper::empty() const { 176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 177 return pending_database_info_.empty(); 178 } 179 180 size_t CannedBrowsingDataDatabaseHelper::GetDatabaseCount() const { 181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 182 return pending_database_info_.size(); 183 } 184 185 const std::set<CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo>& 186 CannedBrowsingDataDatabaseHelper::GetPendingDatabaseInfo() { 187 return pending_database_info_; 188 } 189 190 void CannedBrowsingDataDatabaseHelper::StartFetching( 191 const base::Callback<void(const std::list<DatabaseInfo>&)>& callback) { 192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 193 DCHECK(!callback.is_null()); 194 195 std::list<DatabaseInfo> result; 196 for (std::set<PendingDatabaseInfo>::const_iterator 197 info = pending_database_info_.begin(); 198 info != pending_database_info_.end(); ++info) { 199 DatabaseIdentifier identifier = 200 DatabaseIdentifier::CreateFromOrigin(info->origin); 201 202 result.push_back(DatabaseInfo( 203 identifier, 204 info->name, 205 info->description, 206 0, 207 base::Time())); 208 } 209 210 BrowserThread::PostTask( 211 BrowserThread::UI, FROM_HERE, base::Bind(callback, result)); 212 } 213 214 void CannedBrowsingDataDatabaseHelper::DeleteDatabase( 215 const std::string& origin_identifier, 216 const std::string& name) { 217 GURL origin = 218 webkit_database::DatabaseIdentifier::Parse(origin_identifier).ToOrigin(); 219 for (std::set<PendingDatabaseInfo>::iterator it = 220 pending_database_info_.begin(); 221 it != pending_database_info_.end(); 222 ++it) { 223 if (it->origin == origin && it->name == name) { 224 pending_database_info_.erase(it); 225 break; 226 } 227 } 228 BrowsingDataDatabaseHelper::DeleteDatabase(origin_identifier, name); 229 } 230 231 CannedBrowsingDataDatabaseHelper::~CannedBrowsingDataDatabaseHelper() {} 232