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
DatabaseInfo()20 BrowsingDataDatabaseHelper::DatabaseInfo::DatabaseInfo()
21 : size(0) {
22 }
23
DatabaseInfo(const std::string & host,const std::string & database_name,const std::string & origin_identifier,const std::string & description,const std::string & origin,int64 size,base::Time last_modified)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
~DatabaseInfo()41 BrowsingDataDatabaseHelper::DatabaseInfo::~DatabaseInfo() {}
42
IsFileSchemeData()43 bool BrowsingDataDatabaseHelper::DatabaseInfo::IsFileSchemeData() {
44 return StartsWithASCII(origin_identifier,
45 std::string(chrome::kFileScheme),
46 true);
47 }
48
BrowsingDataDatabaseHelper(Profile * profile)49 BrowsingDataDatabaseHelper::BrowsingDataDatabaseHelper(Profile* profile)
50 : completion_callback_(NULL),
51 is_fetching_(false),
52 tracker_(profile->GetDatabaseTracker()) {
53 }
54
~BrowsingDataDatabaseHelper()55 BrowsingDataDatabaseHelper::~BrowsingDataDatabaseHelper() {
56 }
57
StartFetching(Callback1<const std::vector<DatabaseInfo> &>::Type * callback)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
CancelNotification()70 void BrowsingDataDatabaseHelper::CancelNotification() {
71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
72 completion_callback_.reset(NULL);
73 }
74
DeleteDatabase(const std::string & origin,const std::string & name)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
FetchDatabaseInfoInWebKitThread()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
NotifyInUIThread()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
DeleteDatabaseInWebKitThread(const std::string & origin,const std::string & name)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
PendingDatabaseInfo()145 CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::PendingDatabaseInfo() {}
146
PendingDatabaseInfo(const GURL & origin,const std::string & name,const std::string & description)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
~PendingDatabaseInfo()156 CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::~PendingDatabaseInfo() {}
157
CannedBrowsingDataDatabaseHelper(Profile * profile)158 CannedBrowsingDataDatabaseHelper::CannedBrowsingDataDatabaseHelper(
159 Profile* profile)
160 : BrowsingDataDatabaseHelper(profile),
161 profile_(profile) {
162 }
163
Clone()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
AddDatabase(const GURL & origin,const std::string & name,const std::string & description)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
Reset()184 void CannedBrowsingDataDatabaseHelper::Reset() {
185 base::AutoLock auto_lock(lock_);
186 database_info_.clear();
187 pending_database_info_.clear();
188 }
189
empty() const190 bool CannedBrowsingDataDatabaseHelper::empty() const {
191 base::AutoLock auto_lock(lock_);
192 return database_info_.empty() && pending_database_info_.empty();
193 }
194
StartFetching(Callback1<const std::vector<DatabaseInfo> &>::Type * callback)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
~CannedBrowsingDataDatabaseHelper()206 CannedBrowsingDataDatabaseHelper::~CannedBrowsingDataDatabaseHelper() {}
207
ConvertInfoInWebKitThread()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