blob: 7afea585b8713b6e76b9932fe4a82beac6e0b8d0 [file] [log] [blame]
[email protected]0c7a6b2d2011-02-10 15:27:551// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]2823fb242010-09-23 08:53:262// 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_indexed_db_helper.h"
6
7#include "base/file_util.h"
8#include "base/message_loop.h"
9#include "base/scoped_ptr.h"
10#include "base/string_util.h"
11#include "base/utf_string_conversions.h"
[email protected]ed7e6dd2010-10-12 02:02:4512#include "chrome/browser/browser_thread.h"
[email protected]2823fb242010-09-23 08:53:2613#include "chrome/browser/in_process_webkit/webkit_context.h"
[email protected]8ecad5e2010-12-02 21:18:3314#include "chrome/browser/profiles/profile.h"
[email protected]8bd0fe62011-01-17 06:44:3715#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h"
16#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
17#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
[email protected]2823fb242010-09-23 08:53:2618#include "webkit/glue/webkit_glue.h"
19
20using WebKit::WebSecurityOrigin;
21
22namespace {
23
24class BrowsingDataIndexedDBHelperImpl : public BrowsingDataIndexedDBHelper {
25 public:
26 explicit BrowsingDataIndexedDBHelperImpl(Profile* profile);
27
28 virtual void StartFetching(
29 Callback1<const std::vector<IndexedDBInfo>& >::Type* callback);
30 virtual void CancelNotification();
31 virtual void DeleteIndexedDBFile(const FilePath& file_path);
32
33 private:
34 virtual ~BrowsingDataIndexedDBHelperImpl();
35
36 // Enumerates all indexed database files in the WEBKIT thread.
37 void FetchIndexedDBInfoInWebKitThread();
38 // Notifies the completion callback in the UI thread.
39 void NotifyInUIThread();
40 // Delete a single indexed database file in the WEBKIT thread.
41 void DeleteIndexedDBFileInWebKitThread(const FilePath& file_path);
42
43 Profile* profile_;
44
45 // This only mutates in the WEBKIT thread.
46 std::vector<IndexedDBInfo> indexed_db_info_;
47
48 // This only mutates on the UI thread.
49 scoped_ptr<Callback1<const std::vector<IndexedDBInfo>& >::Type >
50 completion_callback_;
51 // Indicates whether or not we're currently fetching information:
52 // it's true when StartFetching() is called in the UI thread, and it's reset
53 // after we notified the callback in the UI thread.
54 // This only mutates on the UI thread.
55 bool is_fetching_;
56
57 DISALLOW_COPY_AND_ASSIGN(BrowsingDataIndexedDBHelperImpl);
58};
59
60BrowsingDataIndexedDBHelperImpl::BrowsingDataIndexedDBHelperImpl(
61 Profile* profile)
62 : profile_(profile),
63 completion_callback_(NULL),
64 is_fetching_(false) {
65 DCHECK(profile_);
66}
67
68BrowsingDataIndexedDBHelperImpl::~BrowsingDataIndexedDBHelperImpl() {
69}
70
71void BrowsingDataIndexedDBHelperImpl::StartFetching(
72 Callback1<const std::vector<IndexedDBInfo>& >::Type* callback) {
[email protected]d04e7662010-10-10 22:24:4873 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]2823fb242010-09-23 08:53:2674 DCHECK(!is_fetching_);
75 DCHECK(callback);
76 is_fetching_ = true;
77 completion_callback_.reset(callback);
[email protected]d04e7662010-10-10 22:24:4878 BrowserThread::PostTask(
79 BrowserThread::WEBKIT, FROM_HERE,
[email protected]2823fb242010-09-23 08:53:2680 NewRunnableMethod(
81 this,
82 &BrowsingDataIndexedDBHelperImpl::FetchIndexedDBInfoInWebKitThread));
83}
84
85void BrowsingDataIndexedDBHelperImpl::CancelNotification() {
[email protected]d04e7662010-10-10 22:24:4886 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]2823fb242010-09-23 08:53:2687 completion_callback_.reset(NULL);
88}
89
90void BrowsingDataIndexedDBHelperImpl::DeleteIndexedDBFile(
91 const FilePath& file_path) {
[email protected]d04e7662010-10-10 22:24:4892 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
93 BrowserThread::PostTask(
94 BrowserThread::WEBKIT, FROM_HERE,
[email protected]2823fb242010-09-23 08:53:2695 NewRunnableMethod(
96 this,
97 &BrowsingDataIndexedDBHelperImpl::
98 DeleteIndexedDBFileInWebKitThread,
99 file_path));
100}
101
102void BrowsingDataIndexedDBHelperImpl::FetchIndexedDBInfoInWebKitThread() {
[email protected]d04e7662010-10-10 22:24:48103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
[email protected]2823fb242010-09-23 08:53:26104 file_util::FileEnumerator file_enumerator(
105 profile_->GetWebKitContext()->data_path().Append(
106 IndexedDBContext::kIndexedDBDirectory),
107 false, file_util::FileEnumerator::FILES);
108 for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
109 file_path = file_enumerator.Next()) {
110 if (file_path.Extension() == IndexedDBContext::kIndexedDBExtension) {
[email protected]5000ade62010-11-08 23:20:49111 WebSecurityOrigin web_security_origin =
[email protected]0c7a6b2d2011-02-10 15:27:55112 WebSecurityOrigin::createFromDatabaseIdentifier(
[email protected]5000ade62010-11-08 23:20:49113 webkit_glue::FilePathToWebString(file_path.BaseName()));
[email protected]2823fb242010-09-23 08:53:26114 if (EqualsASCII(web_security_origin.protocol(),
115 chrome::kExtensionScheme)) {
116 // Extension state is not considered browsing data.
117 continue;
118 }
119 base::PlatformFileInfo file_info;
120 bool ret = file_util::GetFileInfo(file_path, &file_info);
121 if (ret) {
122 indexed_db_info_.push_back(IndexedDBInfo(
123 web_security_origin.protocol().utf8(),
124 web_security_origin.host().utf8(),
125 web_security_origin.port(),
126 web_security_origin.databaseIdentifier().utf8(),
127 web_security_origin.toString().utf8(),
[email protected]2823fb242010-09-23 08:53:26128 file_path,
129 file_info.size,
130 file_info.last_modified));
131 }
132 }
133 }
134
[email protected]d04e7662010-10-10 22:24:48135 BrowserThread::PostTask(
136 BrowserThread::UI, FROM_HERE,
[email protected]2823fb242010-09-23 08:53:26137 NewRunnableMethod(
138 this, &BrowsingDataIndexedDBHelperImpl::NotifyInUIThread));
139}
140
141void BrowsingDataIndexedDBHelperImpl::NotifyInUIThread() {
[email protected]d04e7662010-10-10 22:24:48142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]2823fb242010-09-23 08:53:26143 DCHECK(is_fetching_);
144 // Note: completion_callback_ mutates only in the UI thread, so it's safe to
145 // test it here.
146 if (completion_callback_ != NULL) {
147 completion_callback_->Run(indexed_db_info_);
148 completion_callback_.reset();
149 }
150 is_fetching_ = false;
151}
152
153void BrowsingDataIndexedDBHelperImpl::DeleteIndexedDBFileInWebKitThread(
154 const FilePath& file_path) {
[email protected]d04e7662010-10-10 22:24:48155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
[email protected]2823fb242010-09-23 08:53:26156 // TODO(jochen): implement this once it's possible to delete indexed DBs.
157}
158
159} // namespace
160
[email protected]d2f05d02011-01-27 18:51:01161BrowsingDataIndexedDBHelper::IndexedDBInfo::IndexedDBInfo(
162 const std::string& protocol,
163 const std::string& host,
164 unsigned short port,
165 const std::string& database_identifier,
166 const std::string& origin,
167 const FilePath& file_path,
168 int64 size,
169 base::Time last_modified)
170 : protocol(protocol),
171 host(host),
172 port(port),
173 database_identifier(database_identifier),
174 origin(origin),
175 file_path(file_path),
176 size(size),
177 last_modified(last_modified) {
178}
179
180BrowsingDataIndexedDBHelper::IndexedDBInfo::~IndexedDBInfo() {}
181
[email protected]2823fb242010-09-23 08:53:26182// static
183BrowsingDataIndexedDBHelper* BrowsingDataIndexedDBHelper::Create(
184 Profile* profile) {
185 return new BrowsingDataIndexedDBHelperImpl(profile);
186}
187
[email protected]0c7a6b2d2011-02-10 15:27:55188CannedBrowsingDataIndexedDBHelper::
189PendingIndexedDBInfo::PendingIndexedDBInfo() {
190}
191
192CannedBrowsingDataIndexedDBHelper::
193PendingIndexedDBInfo::PendingIndexedDBInfo(const GURL& origin,
194 const string16& description)
195 : origin(origin),
196 description(description) {
197}
198
199CannedBrowsingDataIndexedDBHelper::
200PendingIndexedDBInfo::~PendingIndexedDBInfo() {
201}
202
[email protected]2823fb242010-09-23 08:53:26203CannedBrowsingDataIndexedDBHelper::CannedBrowsingDataIndexedDBHelper(
204 Profile* profile)
[email protected]0c7a6b2d2011-02-10 15:27:55205 : profile_(profile),
206 completion_callback_(NULL),
207 is_fetching_(false) {
[email protected]2823fb242010-09-23 08:53:26208 DCHECK(profile);
209}
210
211void CannedBrowsingDataIndexedDBHelper::AddIndexedDB(
[email protected]5000ade62010-11-08 23:20:49212 const GURL& origin, const string16& description) {
[email protected]0c7a6b2d2011-02-10 15:27:55213 base::AutoLock auto_lock(lock_);
214 pending_indexed_db_info_.push_back(PendingIndexedDBInfo(origin, description));
[email protected]2823fb242010-09-23 08:53:26215}
216
217void CannedBrowsingDataIndexedDBHelper::Reset() {
[email protected]0c7a6b2d2011-02-10 15:27:55218 base::AutoLock auto_lock(lock_);
[email protected]2823fb242010-09-23 08:53:26219 indexed_db_info_.clear();
[email protected]0c7a6b2d2011-02-10 15:27:55220 pending_indexed_db_info_.clear();
[email protected]2823fb242010-09-23 08:53:26221}
222
223bool CannedBrowsingDataIndexedDBHelper::empty() const {
[email protected]0c7a6b2d2011-02-10 15:27:55224 base::AutoLock auto_lock(lock_);
225 return indexed_db_info_.empty() && pending_indexed_db_info_.empty();
[email protected]2823fb242010-09-23 08:53:26226}
227
228void CannedBrowsingDataIndexedDBHelper::StartFetching(
229 Callback1<const std::vector<IndexedDBInfo>& >::Type* callback) {
[email protected]0c7a6b2d2011-02-10 15:27:55230 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
231 DCHECK(!is_fetching_);
232 DCHECK(callback);
233 is_fetching_ = true;
234 completion_callback_.reset(callback);
235 BrowserThread::PostTask(BrowserThread::WEBKIT, FROM_HERE, NewRunnableMethod(
236 this,
237 &CannedBrowsingDataIndexedDBHelper::ConvertPendingInfoInWebKitThread));
[email protected]2823fb242010-09-23 08:53:26238}
[email protected]8e383412010-10-19 16:57:03239
240CannedBrowsingDataIndexedDBHelper::~CannedBrowsingDataIndexedDBHelper() {}
[email protected]0c7a6b2d2011-02-10 15:27:55241
242void CannedBrowsingDataIndexedDBHelper::ConvertPendingInfoInWebKitThread() {
243 base::AutoLock auto_lock(lock_);
244 for (std::vector<PendingIndexedDBInfo>::const_iterator
245 info = pending_indexed_db_info_.begin();
246 info != pending_indexed_db_info_.end(); ++info) {
247 WebSecurityOrigin web_security_origin =
248 WebSecurityOrigin::createFromString(
249 UTF8ToUTF16(info->origin.spec()));
250 std::string security_origin(web_security_origin.toString().utf8());
251
252 bool duplicate = false;
253 for (std::vector<IndexedDBInfo>::iterator
254 indexed_db = indexed_db_info_.begin();
255 indexed_db != indexed_db_info_.end(); ++indexed_db) {
256 if (indexed_db->origin == security_origin) {
257 duplicate = true;
258 break;
259 }
260 }
261 if (duplicate)
262 continue;
263
264 indexed_db_info_.push_back(IndexedDBInfo(
265 web_security_origin.protocol().utf8(),
266 web_security_origin.host().utf8(),
267 web_security_origin.port(),
268 web_security_origin.databaseIdentifier().utf8(),
269 security_origin,
270 profile_->GetWebKitContext()->indexed_db_context()->
271 GetIndexedDBFilePath(web_security_origin.databaseIdentifier()),
272 0,
273 base::Time()));
274 }
275 pending_indexed_db_info_.clear();
276
277 BrowserThread::PostTask(
278 BrowserThread::UI, FROM_HERE,
279 NewRunnableMethod(
280 this, &CannedBrowsingDataIndexedDBHelper::NotifyInUIThread));
281}
282
283void CannedBrowsingDataIndexedDBHelper::NotifyInUIThread() {
284 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
285 DCHECK(is_fetching_);
286 // Note: completion_callback_ mutates only in the UI thread, so it's safe to
287 // test it here.
288 if (completion_callback_ != NULL) {
289 completion_callback_->Run(indexed_db_info_);
290 completion_callback_.reset();
291 }
292 is_fetching_ = false;
293}