OLD | NEW |
| (Empty) |
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_indexed_db_helper.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/callback.h" | |
9 #include "base/compiler_specific.h" | |
10 #include "base/file_util.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/message_loop.h" | |
13 #include "base/string_util.h" | |
14 #include "base/utf_string_conversions.h" | |
15 #include "chrome/browser/browsing_data_helper.h" | |
16 #include "chrome/browser/profiles/profile.h" | |
17 #include "content/public/browser/browser_thread.h" | |
18 #include "content/public/browser/indexed_db_context.h" | |
19 #include "webkit/database/database_util.h" | |
20 #include "webkit/glue/webkit_glue.h" | |
21 | |
22 using content::BrowserContext; | |
23 using content::BrowserThread; | |
24 using content::IndexedDBContext; | |
25 using webkit_database::DatabaseUtil; | |
26 | |
27 namespace { | |
28 | |
29 class BrowsingDataIndexedDBHelperImpl : public BrowsingDataIndexedDBHelper { | |
30 public: | |
31 explicit BrowsingDataIndexedDBHelperImpl(Profile* profile); | |
32 | |
33 virtual void StartFetching( | |
34 const base::Callback<void(const std::list<IndexedDBInfo>&)>& | |
35 callback) OVERRIDE; | |
36 virtual void DeleteIndexedDB(const GURL& origin) OVERRIDE; | |
37 | |
38 private: | |
39 virtual ~BrowsingDataIndexedDBHelperImpl(); | |
40 | |
41 // Enumerates all indexed database files in the WEBKIT thread. | |
42 void FetchIndexedDBInfoInWebKitThread(); | |
43 // Notifies the completion callback in the UI thread. | |
44 void NotifyInUIThread(); | |
45 // Delete a single indexed database in the WEBKIT thread. | |
46 void DeleteIndexedDBInWebKitThread(const GURL& origin); | |
47 | |
48 scoped_refptr<IndexedDBContext> indexed_db_context_; | |
49 | |
50 // Access to |indexed_db_info_| is triggered indirectly via the UI thread and | |
51 // guarded by |is_fetching_|. This means |indexed_db_info_| is only accessed | |
52 // while |is_fetching_| is true. The flag |is_fetching_| is only accessed on | |
53 // the UI thread. | |
54 // In the context of this class |indexed_db_info_| is only accessed on the | |
55 // WEBKIT thread. | |
56 std::list<IndexedDBInfo> indexed_db_info_; | |
57 | |
58 // This only mutates on the UI thread. | |
59 base::Callback<void(const std::list<IndexedDBInfo>&)> completion_callback_; | |
60 | |
61 // Indicates whether or not we're currently fetching information: | |
62 // it's true when StartFetching() is called in the UI thread, and it's reset | |
63 // after we notified the callback in the UI thread. | |
64 // This only mutates on the UI thread. | |
65 bool is_fetching_; | |
66 | |
67 DISALLOW_COPY_AND_ASSIGN(BrowsingDataIndexedDBHelperImpl); | |
68 }; | |
69 | |
70 BrowsingDataIndexedDBHelperImpl::BrowsingDataIndexedDBHelperImpl( | |
71 Profile* profile) | |
72 : indexed_db_context_(BrowserContext::GetIndexedDBContext(profile)), | |
73 is_fetching_(false) { | |
74 DCHECK(indexed_db_context_.get()); | |
75 } | |
76 | |
77 BrowsingDataIndexedDBHelperImpl::~BrowsingDataIndexedDBHelperImpl() { | |
78 } | |
79 | |
80 void BrowsingDataIndexedDBHelperImpl::StartFetching( | |
81 const base::Callback<void(const std::list<IndexedDBInfo>&)>& callback) { | |
82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
83 DCHECK(!is_fetching_); | |
84 DCHECK_EQ(false, callback.is_null()); | |
85 | |
86 is_fetching_ = true; | |
87 completion_callback_ = callback; | |
88 BrowserThread::PostTask( | |
89 BrowserThread::WEBKIT_DEPRECATED, FROM_HERE, | |
90 base::Bind( | |
91 &BrowsingDataIndexedDBHelperImpl::FetchIndexedDBInfoInWebKitThread, | |
92 this)); | |
93 } | |
94 | |
95 void BrowsingDataIndexedDBHelperImpl::DeleteIndexedDB( | |
96 const GURL& origin) { | |
97 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
98 BrowserThread::PostTask( | |
99 BrowserThread::WEBKIT_DEPRECATED, FROM_HERE, | |
100 base::Bind( | |
101 &BrowsingDataIndexedDBHelperImpl::DeleteIndexedDBInWebKitThread, this, | |
102 origin)); | |
103 } | |
104 | |
105 void BrowsingDataIndexedDBHelperImpl::FetchIndexedDBInfoInWebKitThread() { | |
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); | |
107 std::vector<GURL> origins = indexed_db_context_->GetAllOrigins(); | |
108 for (std::vector<GURL>::const_iterator iter = origins.begin(); | |
109 iter != origins.end(); ++iter) { | |
110 const GURL& origin = *iter; | |
111 if (!BrowsingDataHelper::HasWebScheme(origin)) | |
112 continue; // Non-websafe state is not considered browsing data. | |
113 | |
114 indexed_db_info_.push_back(IndexedDBInfo( | |
115 origin, | |
116 indexed_db_context_->GetOriginDiskUsage(origin), | |
117 indexed_db_context_->GetOriginLastModified(origin))); | |
118 } | |
119 | |
120 BrowserThread::PostTask( | |
121 BrowserThread::UI, FROM_HERE, | |
122 base::Bind(&BrowsingDataIndexedDBHelperImpl::NotifyInUIThread, this)); | |
123 } | |
124 | |
125 void BrowsingDataIndexedDBHelperImpl::NotifyInUIThread() { | |
126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
127 DCHECK(is_fetching_); | |
128 completion_callback_.Run(indexed_db_info_); | |
129 completion_callback_.Reset(); | |
130 is_fetching_ = false; | |
131 } | |
132 | |
133 void BrowsingDataIndexedDBHelperImpl::DeleteIndexedDBInWebKitThread( | |
134 const GURL& origin) { | |
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); | |
136 indexed_db_context_->DeleteForOrigin(origin); | |
137 } | |
138 | |
139 } // namespace | |
140 | |
141 BrowsingDataIndexedDBHelper::IndexedDBInfo::IndexedDBInfo( | |
142 const GURL& origin, | |
143 int64 size, | |
144 base::Time last_modified) | |
145 : origin(origin), | |
146 size(size), | |
147 last_modified(last_modified) { | |
148 } | |
149 | |
150 BrowsingDataIndexedDBHelper::IndexedDBInfo::~IndexedDBInfo() {} | |
151 | |
152 // static | |
153 BrowsingDataIndexedDBHelper* BrowsingDataIndexedDBHelper::Create( | |
154 Profile* profile) { | |
155 return new BrowsingDataIndexedDBHelperImpl(profile); | |
156 } | |
157 | |
158 CannedBrowsingDataIndexedDBHelper:: | |
159 PendingIndexedDBInfo::PendingIndexedDBInfo(const GURL& origin, | |
160 const string16& name) | |
161 : origin(origin), | |
162 name(name) { | |
163 } | |
164 | |
165 CannedBrowsingDataIndexedDBHelper:: | |
166 PendingIndexedDBInfo::~PendingIndexedDBInfo() { | |
167 } | |
168 | |
169 bool CannedBrowsingDataIndexedDBHelper::PendingIndexedDBInfo::operator<( | |
170 const PendingIndexedDBInfo& other) const { | |
171 if (origin == other.origin) | |
172 return name < other.name; | |
173 return origin < other.origin; | |
174 } | |
175 | |
176 CannedBrowsingDataIndexedDBHelper::CannedBrowsingDataIndexedDBHelper() | |
177 : is_fetching_(false) { | |
178 } | |
179 | |
180 CannedBrowsingDataIndexedDBHelper::~CannedBrowsingDataIndexedDBHelper() {} | |
181 | |
182 CannedBrowsingDataIndexedDBHelper* CannedBrowsingDataIndexedDBHelper::Clone() { | |
183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
184 CannedBrowsingDataIndexedDBHelper* clone = | |
185 new CannedBrowsingDataIndexedDBHelper(); | |
186 | |
187 base::AutoLock auto_lock(lock_); | |
188 clone->pending_indexed_db_info_ = pending_indexed_db_info_; | |
189 clone->indexed_db_info_ = indexed_db_info_; | |
190 return clone; | |
191 } | |
192 | |
193 void CannedBrowsingDataIndexedDBHelper::AddIndexedDB( | |
194 const GURL& origin, const string16& name) { | |
195 if (!BrowsingDataHelper::HasWebScheme(origin)) | |
196 return; // Non-websafe state is not considered browsing data. | |
197 | |
198 base::AutoLock auto_lock(lock_); | |
199 pending_indexed_db_info_.insert(PendingIndexedDBInfo(origin, name)); | |
200 } | |
201 | |
202 void CannedBrowsingDataIndexedDBHelper::Reset() { | |
203 base::AutoLock auto_lock(lock_); | |
204 indexed_db_info_.clear(); | |
205 pending_indexed_db_info_.clear(); | |
206 } | |
207 | |
208 bool CannedBrowsingDataIndexedDBHelper::empty() const { | |
209 base::AutoLock auto_lock(lock_); | |
210 return indexed_db_info_.empty() && pending_indexed_db_info_.empty(); | |
211 } | |
212 | |
213 size_t CannedBrowsingDataIndexedDBHelper::GetIndexedDBCount() const { | |
214 base::AutoLock auto_lock(lock_); | |
215 return pending_indexed_db_info_.size(); | |
216 } | |
217 | |
218 const std::set<CannedBrowsingDataIndexedDBHelper::PendingIndexedDBInfo>& | |
219 CannedBrowsingDataIndexedDBHelper::GetIndexedDBInfo() const { | |
220 base::AutoLock auto_lock(lock_); | |
221 return pending_indexed_db_info_; | |
222 } | |
223 | |
224 void CannedBrowsingDataIndexedDBHelper::StartFetching( | |
225 const base::Callback<void(const std::list<IndexedDBInfo>&)>& callback) { | |
226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
227 DCHECK(!is_fetching_); | |
228 DCHECK_EQ(false, callback.is_null()); | |
229 | |
230 is_fetching_ = true; | |
231 completion_callback_ = callback; | |
232 BrowserThread::PostTask( | |
233 BrowserThread::WEBKIT_DEPRECATED, FROM_HERE, | |
234 base::Bind( | |
235 &CannedBrowsingDataIndexedDBHelper::ConvertPendingInfoInWebKitThread, | |
236 this)); | |
237 } | |
238 | |
239 void CannedBrowsingDataIndexedDBHelper::ConvertPendingInfoInWebKitThread() { | |
240 base::AutoLock auto_lock(lock_); | |
241 indexed_db_info_.clear(); | |
242 for (std::set<PendingIndexedDBInfo>::const_iterator | |
243 info = pending_indexed_db_info_.begin(); | |
244 info != pending_indexed_db_info_.end(); ++info) { | |
245 indexed_db_info_.push_back(IndexedDBInfo( | |
246 info->origin, | |
247 0, | |
248 base::Time())); | |
249 } | |
250 | |
251 BrowserThread::PostTask( | |
252 BrowserThread::UI, FROM_HERE, | |
253 base::Bind(&CannedBrowsingDataIndexedDBHelper::NotifyInUIThread, this)); | |
254 } | |
255 | |
256 void CannedBrowsingDataIndexedDBHelper::NotifyInUIThread() { | |
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
258 DCHECK(is_fetching_); | |
259 | |
260 completion_callback_.Run(indexed_db_info_); | |
261 completion_callback_.Reset(); | |
262 is_fetching_ = false; | |
263 } | |
OLD | NEW |