- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / browsing_data / browsing_data_file_system_helper.cc
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/browsing_data_file_system_helper.h"
6
7 #include "base/bind.h"
8 #include "base/compiler_specific.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/sequenced_task_runner.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/browsing_data/browsing_data_helper.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "webkit/browser/fileapi/file_system_context.h"
17 #include "webkit/browser/fileapi/file_system_quota_util.h"
18 #include "webkit/common/fileapi/file_system_types.h"
19
20 using content::BrowserThread;
21
22 namespace fileapi {
23 class FileSystemContext;
24 }
25
26 namespace {
27
28 // An implementation of the BrowsingDataFileSystemHelper interface that pulls
29 // data from a given |filesystem_context| and returns a list of FileSystemInfo
30 // items to a client.
31 class BrowsingDataFileSystemHelperImpl : public BrowsingDataFileSystemHelper {
32  public:
33   // BrowsingDataFileSystemHelper implementation
34   explicit BrowsingDataFileSystemHelperImpl(
35       fileapi::FileSystemContext* filesystem_context);
36   virtual void StartFetching(const base::Callback<
37       void(const std::list<FileSystemInfo>&)>& callback) OVERRIDE;
38   virtual void DeleteFileSystemOrigin(const GURL& origin) OVERRIDE;
39
40  private:
41   virtual ~BrowsingDataFileSystemHelperImpl();
42
43   // Enumerates all filesystem files, storing the resulting list into
44   // file_system_file_ for later use. This must be called on the file
45   // task runner.
46   void FetchFileSystemInfoInFileThread();
47
48   // Triggers the success callback as the end of a StartFetching workflow. This
49   // must be called on the UI thread.
50   void NotifyOnUIThread();
51
52   // Deletes all file systems associated with |origin|. This must be called on
53   // the file task runner.
54   void DeleteFileSystemOriginInFileThread(const GURL& origin);
55
56   // Returns the file task runner for the |filesystem_context_|.
57   base::SequencedTaskRunner* file_task_runner() {
58     return filesystem_context_->default_file_task_runner();
59   }
60
61   // Keep a reference to the FileSystemContext object for the current profile
62   // for use on the file task runner.
63   scoped_refptr<fileapi::FileSystemContext> filesystem_context_;
64
65   // Holds the current list of file systems returned to the client after
66   // StartFetching is called. Access to |file_system_info_| is triggered
67   // indirectly via the UI thread and guarded by |is_fetching_|. This means
68   // |file_system_info_| is only accessed while |is_fetching_| is true. The
69   // flag |is_fetching_| is only accessed on the UI thread. In the context of
70   // this class |file_system_info_| only mutates on the file task runner.
71   std::list<FileSystemInfo> file_system_info_;
72
73   // Holds the callback passed in at the beginning of the StartFetching workflow
74   // so that it can be triggered via NotifyOnUIThread. This only mutates on the
75   // UI thread.
76   base::Callback<void(const std::list<FileSystemInfo>&)> completion_callback_;
77
78   // Indicates whether or not we're currently fetching information: set to true
79   // when StartFetching is called on the UI thread, and reset to false when
80   // NotifyOnUIThread triggers the success callback.
81   // This property only mutates on the UI thread.
82   bool is_fetching_;
83
84   DISALLOW_COPY_AND_ASSIGN(BrowsingDataFileSystemHelperImpl);
85 };
86
87 BrowsingDataFileSystemHelperImpl::BrowsingDataFileSystemHelperImpl(
88     fileapi::FileSystemContext* filesystem_context)
89     : filesystem_context_(filesystem_context),
90       is_fetching_(false) {
91   DCHECK(filesystem_context_.get());
92 }
93
94 BrowsingDataFileSystemHelperImpl::~BrowsingDataFileSystemHelperImpl() {
95 }
96
97 void BrowsingDataFileSystemHelperImpl::StartFetching(
98     const base::Callback<void(const std::list<FileSystemInfo>&)>& callback) {
99   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
100   DCHECK(!is_fetching_);
101   DCHECK_EQ(false, 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));
109 }
110
111 void BrowsingDataFileSystemHelperImpl::DeleteFileSystemOrigin(
112     const GURL& origin) {
113   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
114   file_task_runner()->PostTask(
115       FROM_HERE,
116       base::Bind(
117           &BrowsingDataFileSystemHelperImpl::DeleteFileSystemOriginInFileThread,
118           this, origin));
119 }
120
121 void BrowsingDataFileSystemHelperImpl::FetchFileSystemInfoInFileThread() {
122   DCHECK(file_task_runner()->RunsTasksOnCurrentThread());
123
124   // We check usage for these filesystem types.
125   const fileapi::FileSystemType types[] = {
126     fileapi::kFileSystemTypeTemporary,
127     fileapi::kFileSystemTypePersistent,
128     fileapi::kFileSystemTypeSyncable,
129   };
130
131   typedef std::map<GURL, FileSystemInfo> OriginInfoMap;
132   OriginInfoMap file_system_info_map;
133   for (size_t i = 0; i < arraysize(types); ++i) {
134     fileapi::FileSystemType type = types[i];
135     fileapi::FileSystemQuotaUtil* quota_util =
136       filesystem_context_->GetQuotaUtil(type);
137     DCHECK(quota_util);
138     std::set<GURL> origins;
139     quota_util->GetOriginsForTypeOnFileThread(type, &origins);
140     for (std::set<GURL>::iterator iter = origins.begin();
141         iter != origins.end(); ++iter) {
142       const GURL& current = *iter;
143       if (!BrowsingDataHelper::HasWebScheme(current))
144         continue;  // Non-websafe state is not considered browsing data.
145       int64 usage = quota_util->GetOriginUsageOnFileThread(
146           filesystem_context_.get(), current, type);
147       OriginInfoMap::iterator inserted =
148           file_system_info_map.insert(
149               std::make_pair(current, FileSystemInfo(current))).first;
150       inserted->second.usage_map[type] = usage;
151     }
152   }
153
154   for (OriginInfoMap::iterator iter = file_system_info_map.begin();
155        iter != file_system_info_map.end(); ++iter) {
156     file_system_info_.push_back(iter->second);
157   }
158
159   BrowserThread::PostTask(
160       BrowserThread::UI, FROM_HERE,
161       base::Bind(&BrowsingDataFileSystemHelperImpl::NotifyOnUIThread, this));
162 }
163
164 void BrowsingDataFileSystemHelperImpl::NotifyOnUIThread() {
165   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
166   DCHECK(is_fetching_);
167   completion_callback_.Run(file_system_info_);
168   completion_callback_.Reset();
169   is_fetching_ = false;
170 }
171
172 void BrowsingDataFileSystemHelperImpl::DeleteFileSystemOriginInFileThread(
173     const GURL& origin) {
174   DCHECK(file_task_runner()->RunsTasksOnCurrentThread());
175   filesystem_context_->DeleteDataForOriginOnFileThread(origin);
176 }
177
178 }  // namespace
179
180 BrowsingDataFileSystemHelper::FileSystemInfo::FileSystemInfo(
181     const GURL& origin) : origin(origin) {}
182
183 BrowsingDataFileSystemHelper::FileSystemInfo::~FileSystemInfo() {}
184
185 // static
186 BrowsingDataFileSystemHelper* BrowsingDataFileSystemHelper::Create(
187     fileapi::FileSystemContext* filesystem_context) {
188   return new BrowsingDataFileSystemHelperImpl(filesystem_context);
189 }
190
191 CannedBrowsingDataFileSystemHelper::CannedBrowsingDataFileSystemHelper(
192     Profile* profile)
193     : is_fetching_(false) {
194 }
195
196 CannedBrowsingDataFileSystemHelper::CannedBrowsingDataFileSystemHelper()
197     : is_fetching_(false) {
198 }
199
200 CannedBrowsingDataFileSystemHelper::~CannedBrowsingDataFileSystemHelper() {}
201
202 CannedBrowsingDataFileSystemHelper*
203     CannedBrowsingDataFileSystemHelper::Clone() {
204   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
205   CannedBrowsingDataFileSystemHelper* clone =
206       new CannedBrowsingDataFileSystemHelper();
207   // This list only mutates on the UI thread, so it's safe to work with it here
208   // (given the DCHECK above).
209   clone->file_system_info_ = file_system_info_;
210   return clone;
211 }
212
213 void CannedBrowsingDataFileSystemHelper::AddFileSystem(
214     const GURL& origin, const fileapi::FileSystemType type, const int64 size) {
215   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
216   // This canned implementation of AddFileSystem uses an O(n^2) algorithm; which
217   // is fine, as it isn't meant for use in a high-volume context. If it turns
218   // out that we want to start using this in a context with many, many origins,
219   // we should think about reworking the implementation.
220   bool duplicate_origin = false;
221   for (std::list<FileSystemInfo>::iterator
222            file_system = file_system_info_.begin();
223        file_system != file_system_info_.end();
224        ++file_system) {
225     if (file_system->origin == origin) {
226       file_system->usage_map[type] = size;
227       duplicate_origin = true;
228       break;
229     }
230   }
231   if (duplicate_origin)
232     return;
233
234   if (!BrowsingDataHelper::HasWebScheme(origin))
235     return;  // Non-websafe state is not considered browsing data.
236
237   FileSystemInfo info(origin);
238   info.usage_map[type] = size;
239   file_system_info_.push_back(info);
240 }
241
242 void CannedBrowsingDataFileSystemHelper::Reset() {
243   file_system_info_.clear();
244 }
245
246 bool CannedBrowsingDataFileSystemHelper::empty() const {
247   return file_system_info_.empty();
248 }
249
250 size_t CannedBrowsingDataFileSystemHelper::GetFileSystemCount() const {
251   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
252   return file_system_info_.size();
253 }
254
255 void CannedBrowsingDataFileSystemHelper::StartFetching(
256     const base::Callback<void(const std::list<FileSystemInfo>&)>& callback) {
257   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
258   DCHECK(!is_fetching_);
259   DCHECK_EQ(false, callback.is_null());
260   is_fetching_ = true;
261   completion_callback_ = callback;
262
263   BrowserThread::PostTask(
264       BrowserThread::UI, FROM_HERE,
265       base::Bind(&CannedBrowsingDataFileSystemHelper::NotifyOnUIThread, this));
266 }
267
268 void CannedBrowsingDataFileSystemHelper::NotifyOnUIThread() {
269   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
270   DCHECK(is_fetching_);
271   completion_callback_.Run(file_system_info_);
272   completion_callback_.Reset();
273   is_fetching_ = false;
274 }