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
);
37 virtual void StartFetching(const base::Callback
<
38 void(const std::list
<FileSystemInfo
>&)>& callback
) override
;
39 virtual void DeleteFileSystemOrigin(const GURL
& origin
) override
;
42 virtual ~BrowsingDataFileSystemHelperImpl();
44 // Enumerates all filesystem files, storing the resulting list into
45 // file_system_file_ for later use. This must be called on the file
47 void FetchFileSystemInfoInFileThread();
49 // Triggers the success callback as the end of a StartFetching workflow. This
50 // must be called on the UI thread.
51 void NotifyOnUIThread();
53 // Deletes all file systems associated with |origin|. This must be called on
54 // the file task runner.
55 void DeleteFileSystemOriginInFileThread(const GURL
& origin
);
57 // Returns the file task runner for the |filesystem_context_|.
58 base::SequencedTaskRunner
* file_task_runner() {
59 return filesystem_context_
->default_file_task_runner();
62 // Keep a reference to the FileSystemContext object for the current profile
63 // for use on the file task runner.
64 scoped_refptr
<storage::FileSystemContext
> filesystem_context_
;
66 // Holds the current list of file systems returned to the client after
67 // StartFetching is called. Access to |file_system_info_| is triggered
68 // indirectly via the UI thread and guarded by |is_fetching_|. This means
69 // |file_system_info_| is only accessed while |is_fetching_| is true. The
70 // flag |is_fetching_| is only accessed on the UI thread. In the context of
71 // this class |file_system_info_| only mutates on the file task runner.
72 std::list
<FileSystemInfo
> file_system_info_
;
74 // Holds the callback passed in at the beginning of the StartFetching workflow
75 // so that it can be triggered via NotifyOnUIThread. This only mutates on the
77 base::Callback
<void(const std::list
<FileSystemInfo
>&)> completion_callback_
;
79 // Indicates whether or not we're currently fetching information: set to true
80 // when StartFetching is called on the UI thread, and reset to false when
81 // NotifyOnUIThread triggers the success callback.
82 // This property only mutates on the UI thread.
85 DISALLOW_COPY_AND_ASSIGN(BrowsingDataFileSystemHelperImpl
);
88 BrowsingDataFileSystemHelperImpl::BrowsingDataFileSystemHelperImpl(
89 storage::FileSystemContext
* filesystem_context
)
90 : filesystem_context_(filesystem_context
), is_fetching_(false) {
91 DCHECK(filesystem_context_
.get());
94 BrowsingDataFileSystemHelperImpl::~BrowsingDataFileSystemHelperImpl() {
97 void BrowsingDataFileSystemHelperImpl::StartFetching(
98 const base::Callback
<void(const std::list
<FileSystemInfo
>&)>& callback
) {
99 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
100 DCHECK(!is_fetching_
);
101 DCHECK(!callback
.is_null());
103 completion_callback_
= callback
;
104 file_task_runner()->PostTask(
107 &BrowsingDataFileSystemHelperImpl::FetchFileSystemInfoInFileThread
,
111 void BrowsingDataFileSystemHelperImpl::DeleteFileSystemOrigin(
112 const GURL
& origin
) {
113 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
114 file_task_runner()->PostTask(
117 &BrowsingDataFileSystemHelperImpl::DeleteFileSystemOriginInFileThread
,
121 void BrowsingDataFileSystemHelperImpl::FetchFileSystemInfoInFileThread() {
122 DCHECK(file_task_runner()->RunsTasksOnCurrentThread());
124 // We check usage for these filesystem types.
125 const storage::FileSystemType types
[] = {
126 storage::kFileSystemTypeTemporary
,
127 storage::kFileSystemTypePersistent
,
128 #if defined(ENABLE_EXTENSIONS)
129 storage::kFileSystemTypeSyncable
,
133 typedef std::map
<GURL
, FileSystemInfo
> OriginInfoMap
;
134 OriginInfoMap file_system_info_map
;
135 for (size_t i
= 0; i
< arraysize(types
); ++i
) {
136 storage::FileSystemType type
= types
[i
];
137 storage::FileSystemQuotaUtil
* quota_util
=
138 filesystem_context_
->GetQuotaUtil(type
);
140 std::set
<GURL
> origins
;
141 quota_util
->GetOriginsForTypeOnFileTaskRunner(type
, &origins
);
142 for (std::set
<GURL
>::iterator iter
= origins
.begin();
143 iter
!= origins
.end(); ++iter
) {
144 const GURL
& current
= *iter
;
145 if (!BrowsingDataHelper::HasWebScheme(current
))
146 continue; // Non-websafe state is not considered browsing data.
147 int64 usage
= quota_util
->GetOriginUsageOnFileTaskRunner(
148 filesystem_context_
.get(), current
, type
);
149 OriginInfoMap::iterator inserted
=
150 file_system_info_map
.insert(
151 std::make_pair(current
, FileSystemInfo(current
))).first
;
152 inserted
->second
.usage_map
[type
] = usage
;
156 for (OriginInfoMap::iterator iter
= file_system_info_map
.begin();
157 iter
!= file_system_info_map
.end(); ++iter
) {
158 file_system_info_
.push_back(iter
->second
);
161 BrowserThread::PostTask(
162 BrowserThread::UI
, FROM_HERE
,
163 base::Bind(&BrowsingDataFileSystemHelperImpl::NotifyOnUIThread
, this));
166 void BrowsingDataFileSystemHelperImpl::NotifyOnUIThread() {
167 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
168 DCHECK(is_fetching_
);
169 completion_callback_
.Run(file_system_info_
);
170 completion_callback_
.Reset();
171 is_fetching_
= false;
174 void BrowsingDataFileSystemHelperImpl::DeleteFileSystemOriginInFileThread(
175 const GURL
& origin
) {
176 DCHECK(file_task_runner()->RunsTasksOnCurrentThread());
177 filesystem_context_
->DeleteDataForOriginOnFileTaskRunner(origin
);
182 BrowsingDataFileSystemHelper::FileSystemInfo::FileSystemInfo(
183 const GURL
& origin
) : origin(origin
) {}
185 BrowsingDataFileSystemHelper::FileSystemInfo::~FileSystemInfo() {}
188 BrowsingDataFileSystemHelper
* BrowsingDataFileSystemHelper::Create(
189 storage::FileSystemContext
* filesystem_context
) {
190 return new BrowsingDataFileSystemHelperImpl(filesystem_context
);
193 CannedBrowsingDataFileSystemHelper::CannedBrowsingDataFileSystemHelper(
197 CannedBrowsingDataFileSystemHelper::~CannedBrowsingDataFileSystemHelper() {}
199 void CannedBrowsingDataFileSystemHelper::AddFileSystem(
201 const storage::FileSystemType type
,
203 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
204 // This canned implementation of AddFileSystem uses an O(n^2) algorithm; which
205 // is fine, as it isn't meant for use in a high-volume context. If it turns
206 // out that we want to start using this in a context with many, many origins,
207 // we should think about reworking the implementation.
208 bool duplicate_origin
= false;
209 for (std::list
<FileSystemInfo
>::iterator
210 file_system
= file_system_info_
.begin();
211 file_system
!= file_system_info_
.end();
213 if (file_system
->origin
== origin
) {
214 file_system
->usage_map
[type
] = size
;
215 duplicate_origin
= true;
219 if (duplicate_origin
)
222 if (!BrowsingDataHelper::HasWebScheme(origin
))
223 return; // Non-websafe state is not considered browsing data.
225 FileSystemInfo
info(origin
);
226 info
.usage_map
[type
] = size
;
227 file_system_info_
.push_back(info
);
230 void CannedBrowsingDataFileSystemHelper::Reset() {
231 file_system_info_
.clear();
234 bool CannedBrowsingDataFileSystemHelper::empty() const {
235 return file_system_info_
.empty();
238 size_t CannedBrowsingDataFileSystemHelper::GetFileSystemCount() const {
239 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
240 return file_system_info_
.size();
243 void CannedBrowsingDataFileSystemHelper::StartFetching(
244 const base::Callback
<void(const std::list
<FileSystemInfo
>&)>& callback
) {
245 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
246 DCHECK(!callback
.is_null());
248 BrowserThread::PostTask(
249 BrowserThread::UI
, FROM_HERE
, base::Bind(callback
, file_system_info_
));