Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / browsing_data / browsing_data_file_system_helper.cc
blob0df684214ee80fc8e0808d31b6dd098132909e0a
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"
7 #include <set>
9 #include "base/bind.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;
23 namespace storage {
24 class FileSystemContext;
27 namespace {
29 // An implementation of the BrowsingDataFileSystemHelper interface that pulls
30 // data from a given |filesystem_context| and returns a list of FileSystemInfo
31 // items to a client.
32 class BrowsingDataFileSystemHelperImpl : public BrowsingDataFileSystemHelper {
33 public:
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;
41 private:
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
46 // task runner.
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
76 // UI thread.
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.
83 bool is_fetching_;
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());
102 is_fetching_ = true;
103 completion_callback_ = callback;
104 file_task_runner()->PostTask(
105 FROM_HERE,
106 base::Bind(
107 &BrowsingDataFileSystemHelperImpl::FetchFileSystemInfoInFileThread,
108 this));
111 void BrowsingDataFileSystemHelperImpl::DeleteFileSystemOrigin(
112 const GURL& origin) {
113 DCHECK_CURRENTLY_ON(BrowserThread::UI);
114 file_task_runner()->PostTask(
115 FROM_HERE,
116 base::Bind(
117 &BrowsingDataFileSystemHelperImpl::DeleteFileSystemOriginInFileThread,
118 this, origin));
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,
130 #endif
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);
139 DCHECK(quota_util);
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);
180 } // namespace
182 BrowsingDataFileSystemHelper::FileSystemInfo::FileSystemInfo(
183 const GURL& origin) : origin(origin) {}
185 BrowsingDataFileSystemHelper::FileSystemInfo::~FileSystemInfo() {}
187 // static
188 BrowsingDataFileSystemHelper* BrowsingDataFileSystemHelper::Create(
189 storage::FileSystemContext* filesystem_context) {
190 return new BrowsingDataFileSystemHelperImpl(filesystem_context);
193 CannedBrowsingDataFileSystemHelper::CannedBrowsingDataFileSystemHelper(
194 Profile* profile) {
197 CannedBrowsingDataFileSystemHelper::~CannedBrowsingDataFileSystemHelper() {}
199 void CannedBrowsingDataFileSystemHelper::AddFileSystem(
200 const GURL& origin,
201 const storage::FileSystemType type,
202 const int64 size) {
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();
212 ++file_system) {
213 if (file_system->origin == origin) {
214 file_system->usage_map[type] = size;
215 duplicate_origin = true;
216 break;
219 if (duplicate_origin)
220 return;
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_));