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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/browsing_data_database_helper.h" 6 7 #include "base/callback.h" 8 #include "base/file_util.h" 9 #include "base/message_loop.h" 10 #include "base/utf_string_conversions.h" 11 #include "chrome/browser/profiles/profile.h" 12 #include "content/browser/browser_thread.h" 13 #include "net/base/net_errors.h" 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h" 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" 17 18 using WebKit::WebSecurityOrigin; 19 20 BrowsingDataDatabaseHelper::DatabaseInfo::DatabaseInfo() 21 : size(0) { 22 } 23 24 BrowsingDataDatabaseHelper::DatabaseInfo::DatabaseInfo( 25 const std::string& host, 26 const std::string& database_name, 27 const std::string& origin_identifier, 28 const std::string& description, 29 const std::string& origin, 30 int64 size, 31 base::Time last_modified) 32 : host(host), 33 database_name(database_name), 34 origin_identifier(origin_identifier), 35 description(description), 36 origin(origin), 37 size(size), 38 last_modified(last_modified) { 39 } 40 41 BrowsingDataDatabaseHelper::DatabaseInfo::~DatabaseInfo() {} 42 43 bool BrowsingDataDatabaseHelper::DatabaseInfo::IsFileSchemeData() { 44 return StartsWithASCII(origin_identifier, 45 std::string(chrome::kFileScheme), 46 true); 47 } 48 49 BrowsingDataDatabaseHelper::BrowsingDataDatabaseHelper(Profile* profile) 50 : completion_callback_(NULL), 51 is_fetching_(false), 52 tracker_(profile->GetDatabaseTracker()) { 53 } 54 55 BrowsingDataDatabaseHelper::~BrowsingDataDatabaseHelper() { 56 } 57 58 void BrowsingDataDatabaseHelper::StartFetching( 59 Callback1<const std::vector<DatabaseInfo>& >::Type* callback) { 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 61 DCHECK(!is_fetching_); 62 DCHECK(callback); 63 is_fetching_ = true; 64 database_info_.clear(); 65 completion_callback_.reset(callback); 66 BrowserThread::PostTask(BrowserThread::WEBKIT, FROM_HERE, NewRunnableMethod( 67 this, &BrowsingDataDatabaseHelper::FetchDatabaseInfoInWebKitThread)); 68 } 69 70 void BrowsingDataDatabaseHelper::CancelNotification() { 71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 72 completion_callback_.reset(NULL); 73 } 74 75 void BrowsingDataDatabaseHelper::DeleteDatabase(const std::string& origin, 76 const std::string& name) { 77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 78 BrowserThread::PostTask(BrowserThread::WEBKIT, FROM_HERE, NewRunnableMethod( 79 this, &BrowsingDataDatabaseHelper::DeleteDatabaseInWebKitThread, origin, 80 name)); 81 } 82 83 void BrowsingDataDatabaseHelper::FetchDatabaseInfoInWebKitThread() { 84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); 85 std::vector<webkit_database::OriginInfo> origins_info; 86 if (tracker_.get() && tracker_->GetAllOriginsInfo(&origins_info)) { 87 for (std::vector<webkit_database::OriginInfo>::const_iterator ori = 88 origins_info.begin(); ori != origins_info.end(); ++ori) { 89 const std::string origin_identifier(UTF16ToUTF8(ori->GetOrigin())); 90 if (StartsWithASCII(origin_identifier, 91 std::string(chrome::kExtensionScheme), 92 true)) { 93 // Extension state is not considered browsing data. 94 continue; 95 } 96 WebSecurityOrigin web_security_origin = 97 WebSecurityOrigin::createFromDatabaseIdentifier( 98 ori->GetOrigin()); 99 std::vector<string16> databases; 100 ori->GetAllDatabaseNames(&databases); 101 for (std::vector<string16>::const_iterator db = databases.begin(); 102 db != databases.end(); ++db) { 103 FilePath file_path = tracker_->GetFullDBFilePath(ori->GetOrigin(), *db); 104 base::PlatformFileInfo file_info; 105 if (file_util::GetFileInfo(file_path, &file_info)) { 106 database_info_.push_back(DatabaseInfo( 107 web_security_origin.host().utf8(), 108 UTF16ToUTF8(*db), 109 origin_identifier, 110 UTF16ToUTF8(ori->GetDatabaseDescription(*db)), 111 web_security_origin.toString().utf8(), 112 file_info.size, 113 file_info.last_modified)); 114 } 115 } 116 } 117 } 118 119 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod( 120 this, &BrowsingDataDatabaseHelper::NotifyInUIThread)); 121 } 122 123 void BrowsingDataDatabaseHelper::NotifyInUIThread() { 124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 125 DCHECK(is_fetching_); 126 // Note: completion_callback_ mutates only in the UI thread, so it's safe to 127 // test it here. 128 if (completion_callback_ != NULL) { 129 completion_callback_->Run(database_info_); 130 completion_callback_.reset(); 131 } 132 is_fetching_ = false; 133 database_info_.clear(); 134 } 135 136 void BrowsingDataDatabaseHelper::DeleteDatabaseInWebKitThread( 137 const std::string& origin, 138 const std::string& name) { 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); 140 if (!tracker_.get()) 141 return; 142 tracker_->DeleteDatabase(UTF8ToUTF16(origin), UTF8ToUTF16(name), NULL); 143 } 144 145 CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::PendingDatabaseInfo() {} 146 147 CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::PendingDatabaseInfo( 148 const GURL& origin, 149 const std::string& name, 150 const std::string& description) 151 : origin(origin), 152 name(name), 153 description(description) { 154 } 155 156 CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::~PendingDatabaseInfo() {} 157 158 CannedBrowsingDataDatabaseHelper::CannedBrowsingDataDatabaseHelper( 159 Profile* profile) 160 : BrowsingDataDatabaseHelper(profile), 161 profile_(profile) { 162 } 163 164 CannedBrowsingDataDatabaseHelper* CannedBrowsingDataDatabaseHelper::Clone() { 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 166 CannedBrowsingDataDatabaseHelper* clone = 167 new CannedBrowsingDataDatabaseHelper(profile_); 168 169 base::AutoLock auto_lock(lock_); 170 clone->pending_database_info_ = pending_database_info_; 171 clone->database_info_ = database_info_; 172 return clone; 173 } 174 175 void CannedBrowsingDataDatabaseHelper::AddDatabase( 176 const GURL& origin, 177 const std::string& name, 178 const std::string& description) { 179 base::AutoLock auto_lock(lock_); 180 pending_database_info_.push_back(PendingDatabaseInfo( 181 origin, name, description)); 182 } 183 184 void CannedBrowsingDataDatabaseHelper::Reset() { 185 base::AutoLock auto_lock(lock_); 186 database_info_.clear(); 187 pending_database_info_.clear(); 188 } 189 190 bool CannedBrowsingDataDatabaseHelper::empty() const { 191 base::AutoLock auto_lock(lock_); 192 return database_info_.empty() && pending_database_info_.empty(); 193 } 194 195 void CannedBrowsingDataDatabaseHelper::StartFetching( 196 Callback1<const std::vector<DatabaseInfo>& >::Type* callback) { 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 198 DCHECK(!is_fetching_); 199 DCHECK(callback); 200 is_fetching_ = true; 201 completion_callback_.reset(callback); 202 BrowserThread::PostTask(BrowserThread::WEBKIT, FROM_HERE, NewRunnableMethod( 203 this, &CannedBrowsingDataDatabaseHelper::ConvertInfoInWebKitThread)); 204 } 205 206 CannedBrowsingDataDatabaseHelper::~CannedBrowsingDataDatabaseHelper() {} 207 208 void CannedBrowsingDataDatabaseHelper::ConvertInfoInWebKitThread() { 209 base::AutoLock auto_lock(lock_); 210 for (std::vector<PendingDatabaseInfo>::const_iterator 211 info = pending_database_info_.begin(); 212 info != pending_database_info_.end(); ++info) { 213 WebSecurityOrigin web_security_origin = 214 WebSecurityOrigin::createFromString( 215 UTF8ToUTF16(info->origin.spec())); 216 std::string origin_identifier = 217 web_security_origin.databaseIdentifier().utf8(); 218 219 bool duplicate = false; 220 for (std::vector<DatabaseInfo>::iterator database = database_info_.begin(); 221 database != database_info_.end(); ++database) { 222 if (database->origin_identifier == origin_identifier && 223 database->database_name == info->name) { 224 duplicate = true; 225 break; 226 } 227 } 228 if (duplicate) 229 continue; 230 231 database_info_.push_back(DatabaseInfo( 232 web_security_origin.host().utf8(), 233 info->name, 234 origin_identifier, 235 info->description, 236 web_security_origin.toString().utf8(), 237 0, 238 base::Time())); 239 } 240 pending_database_info_.clear(); 241 242 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod( 243 this, &CannedBrowsingDataDatabaseHelper::NotifyInUIThread)); 244 } 245