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.
5 #include "chrome/browser/browsing_data/browsing_data_file_system_helper.h"
10 #include "base/compiler_specific.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/sequenced_task_runner.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/browsing_data/browsing_data_helper.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "storage/browser/fileapi/file_system_context.h"
18 #include "storage/browser/fileapi/file_system_quota_util.h"
19 #include "storage/common/fileapi/file_system_types.h"
21 using content::BrowserThread
;
24 class FileSystemContext
;
29 // An implementation of the BrowsingDataFileSystemHelper interface that pulls
30 // data from a given |filesystem_context| and returns a list of FileSystemInfo
32 class BrowsingDataFileSystemHelperImpl
: public BrowsingDataFileSystemHelper
{
34 // BrowsingDataFileSystemHelper implementation
35 explicit BrowsingDataFileSystemHelperImpl(
36 storage::FileSystemContext
* filesystem_context
);
38 const base::Callback
<void(const std::list
<FileSystemInfo
>&)>& callback
)
40 void DeleteFileSystemOrigin(const GURL
& origin
) override
;
43 ~BrowsingDataFileSystemHelperImpl() override
;
45 // Enumerates all filesystem files, storing the resulting list into
46 // file_system_file_ for later use. This must be called on the file
48 void FetchFileSystemInfoInFileThread();
50 // Triggers the success callback as the end of a StartFetching workflow. This
51 // must be called on the UI thread.
52 void NotifyOnUIThread();
54 // Deletes all file systems associated with |origin|. This must be called on
55 // the file task runner.
56 void DeleteFileSystemOriginInFileThread(const GURL
& origin
);
58 // Returns the file task runner for the |filesystem_context_|.
59 base::SequencedTaskRunner
* file_task_runner() {
60 return filesystem_context_
->default_file_task_runner();
63 // Keep a reference to the FileSystemContext object for the current profile
64 // for use on the file task runner.
65 scoped_refptr
<storage::FileSystemContext
> filesystem_context_
;
67 // Holds the current list of file systems returned to the client after
68 // StartFetching is called. Access to |file_system_info_| is triggered
69 // indirectly via the UI thread and guarded by |is_fetching_|. This means
70 // |file_system_info_| is only accessed while |is_fetching_| is true. The
71 // flag |is_fetching_| is only accessed on the UI thread. In the context of
72 // this class |file_system_info_| only mutates on the file task runner.
73 std::list
<FileSystemInfo
> file_system_info_
;
75 // Holds the callback passed in at the beginning of the StartFetching workflow
76 // so that it can be triggered via NotifyOnUIThread. This only mutates on the
78 base::Callback
<void(const std::list
<FileSystemInfo
>&)> completion_callback_
;
80 // Indicates whether or not we're currently fetching information: set to true
81 // when StartFetching is called on the UI thread, and reset to false when
82 // NotifyOnUIThread triggers the success callback.
83 // This property only mutates on the UI thread.
86 DISALLOW_COPY_AND_ASSIGN(BrowsingDataFileSystemHelperImpl
);
89 BrowsingDataFileSystemHelperImpl::BrowsingDataFileSystemHelperImpl(
90 storage::FileSystemContext
* filesystem_context
)
91 : filesystem_context_(filesystem_context
), is_fetching_(false) {
92 DCHECK(filesystem_context_
.get());
95 BrowsingDataFileSystemHelperImpl::~BrowsingDataFileSystemHelperImpl() {
98 void BrowsingDataFileSystemHelperImpl::StartFetching(
99 const base::Callback
<void(const std::list
<FileSystemInfo
>&)>& callback
) {
100 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
101 DCHECK(!is_fetching_
);
102 DCHECK(!callback
.is_null());
104 completion_callback_
= callback
;
105 file_task_runner()->PostTask(
108 &BrowsingDataFileSystemHelperImpl::FetchFileSystemInfoInFileThread
,
112 void BrowsingDataFileSystemHelperImpl::DeleteFileSystemOrigin(
113 const GURL
& origin
) {
114 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
115 file_task_runner()->PostTask(
118 &BrowsingDataFileSystemHelperImpl::DeleteFileSystemOriginInFileThread
,
122 void BrowsingDataFileSystemHelperImpl::FetchFileSystemInfoInFileThread() {
123 DCHECK(file_task_runner()->RunsTasksOnCurrentThread());
125 // We check usage for these filesystem types.
126 const storage::FileSystemType types
[] = {
127 storage::kFileSystemTypeTemporary
,
128 storage::kFileSystemTypePersistent
,
129 #if defined(ENABLE_EXTENSIONS)
130 storage::kFileSystemTypeSyncable
,
134 typedef std::map
<GURL
, FileSystemInfo
> OriginInfoMap
;
135 OriginInfoMap file_system_info_map
;
136 for (size_t i
= 0; i
< arraysize(types
); ++i
) {
137 storage::FileSystemType type
= types
[i
];
138 storage::FileSystemQuotaUtil
* quota_util
=
139 filesystem_context_
->GetQuotaUtil(type
);
141 std::set
<GURL
> origins
;
142 quota_util
->GetOriginsForTypeOnFileTaskRunner(type
, &origins
);
143 for (std::set
<GURL
>::iterator iter
= origins
.begin();
144 iter
!= origins
.end(); ++iter
) {
145 const GURL
& current
= *iter
;
146 if (!BrowsingDataHelper::HasWebScheme(current
))
147 continue; // Non-websafe state is not considered browsing data.
148 int64 usage
= quota_util
->GetOriginUsageOnFileTaskRunner(
149 filesystem_context_
.get(), current
, type
);
150 OriginInfoMap::iterator inserted
=
151 file_system_info_map
.insert(
152 std::make_pair(current
, FileSystemInfo(current
))).first
;
153 inserted
->second
.usage_map
[type
] = usage
;
157 for (OriginInfoMap::iterator iter
= file_system_info_map
.begin();
158 iter
!= file_system_info_map
.end(); ++iter
) {
159 file_system_info_
.push_back(iter
->second
);
162 BrowserThread::PostTask(
163 BrowserThread::UI
, FROM_HERE
,
164 base::Bind(&BrowsingDataFileSystemHelperImpl::NotifyOnUIThread
, this));
167 void BrowsingDataFileSystemHelperImpl::NotifyOnUIThread() {
168 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
169 DCHECK(is_fetching_
);
170 completion_callback_
.Run(file_system_info_
);
171 completion_callback_
.Reset();
172 is_fetching_
= false;
175 void BrowsingDataFileSystemHelperImpl::DeleteFileSystemOriginInFileThread(
176 const GURL
& origin
) {
177 DCHECK(file_task_runner()->RunsTasksOnCurrentThread());
178 filesystem_context_
->DeleteDataForOriginOnFileTaskRunner(origin
);
183 BrowsingDataFileSystemHelper::FileSystemInfo::FileSystemInfo(
184 const GURL
& origin
) : origin(origin
) {}
186 BrowsingDataFileSystemHelper::FileSystemInfo::~FileSystemInfo() {}
189 BrowsingDataFileSystemHelper
* BrowsingDataFileSystemHelper::Create(
190 storage::FileSystemContext
* filesystem_context
) {
191 return new BrowsingDataFileSystemHelperImpl(filesystem_context
);
194 CannedBrowsingDataFileSystemHelper::CannedBrowsingDataFileSystemHelper(
198 CannedBrowsingDataFileSystemHelper::~CannedBrowsingDataFileSystemHelper() {}
200 void CannedBrowsingDataFileSystemHelper::AddFileSystem(
202 const storage::FileSystemType type
,
204 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
205 // This canned implementation of AddFileSystem uses an O(n^2) algorithm; which
206 // is fine, as it isn't meant for use in a high-volume context. If it turns
207 // out that we want to start using this in a context with many, many origins,
208 // we should think about reworking the implementation.
209 bool duplicate_origin
= false;
210 for (std::list
<FileSystemInfo
>::iterator
211 file_system
= file_system_info_
.begin();
212 file_system
!= file_system_info_
.end();
214 if (file_system
->origin
== origin
) {
215 file_system
->usage_map
[type
] = size
;
216 duplicate_origin
= true;
220 if (duplicate_origin
)
223 if (!BrowsingDataHelper::HasWebScheme(origin
))
224 return; // Non-websafe state is not considered browsing data.
226 FileSystemInfo
info(origin
);
227 info
.usage_map
[type
] = size
;
228 file_system_info_
.push_back(info
);
231 void CannedBrowsingDataFileSystemHelper::Reset() {
232 file_system_info_
.clear();
235 bool CannedBrowsingDataFileSystemHelper::empty() const {
236 return file_system_info_
.empty();
239 size_t CannedBrowsingDataFileSystemHelper::GetFileSystemCount() const {
240 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
241 return file_system_info_
.size();
244 void CannedBrowsingDataFileSystemHelper::StartFetching(
245 const base::Callback
<void(const std::list
<FileSystemInfo
>&)>& callback
) {
246 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
247 DCHECK(!callback
.is_null());
249 BrowserThread::PostTask(
250 BrowserThread::UI
, FROM_HERE
, base::Bind(callback
, file_system_info_
));