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_database_helper.h"
6
7#include "base/bind.h"
8#include "base/callback.h"
9#include "base/file_util.h"
10#include "base/message_loop/message_loop.h"
11#include "base/strings/utf_string_conversions.h"
12#include "chrome/browser/browsing_data/browsing_data_helper.h"
13#include "chrome/browser/profiles/profile.h"
14#include "content/public/browser/browser_thread.h"
15#include "content/public/browser/storage_partition.h"
16#include "net/base/completion_callback.h"
17#include "net/base/net_errors.h"
18#include "webkit/common/database/database_identifier.h"
19
20using content::BrowserContext;
21using content::BrowserThread;
22using webkit_database::DatabaseIdentifier;
23
24BrowsingDataDatabaseHelper::DatabaseInfo::DatabaseInfo(
25    const DatabaseIdentifier& identifier,
26    const std::string& database_name,
27    const std::string& description,
28    int64 size,
29    base::Time last_modified)
30    : identifier(identifier),
31      database_name(database_name),
32      description(description),
33      size(size),
34      last_modified(last_modified) {
35}
36
37BrowsingDataDatabaseHelper::DatabaseInfo::~DatabaseInfo() {}
38
39BrowsingDataDatabaseHelper::BrowsingDataDatabaseHelper(Profile* profile)
40    : is_fetching_(false),
41      tracker_(BrowserContext::
42                  GetDefaultStoragePartition(profile)->GetDatabaseTracker()) {
43}
44
45BrowsingDataDatabaseHelper::~BrowsingDataDatabaseHelper() {
46}
47
48void BrowsingDataDatabaseHelper::StartFetching(
49    const base::Callback<void(const std::list<DatabaseInfo>&)>& callback) {
50  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
51  DCHECK(!is_fetching_);
52  DCHECK_EQ(false, callback.is_null());
53
54  is_fetching_ = true;
55  database_info_.clear();
56  completion_callback_ = callback;
57  BrowserThread::PostTask(
58      BrowserThread::FILE, FROM_HERE,
59      base::Bind(&BrowsingDataDatabaseHelper::FetchDatabaseInfoOnFileThread,
60                 this));
61}
62
63void BrowsingDataDatabaseHelper::DeleteDatabase(const std::string& origin,
64                                                const std::string& name) {
65  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
66  BrowserThread::PostTask(
67      BrowserThread::FILE, FROM_HERE,
68      base::Bind(&BrowsingDataDatabaseHelper::DeleteDatabaseOnFileThread, this,
69                 origin, name));
70}
71
72void BrowsingDataDatabaseHelper::FetchDatabaseInfoOnFileThread() {
73  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
74  std::vector<webkit_database::OriginInfo> origins_info;
75  if (tracker_.get() && tracker_->GetAllOriginsInfo(&origins_info)) {
76    for (std::vector<webkit_database::OriginInfo>::const_iterator ori =
77         origins_info.begin(); ori != origins_info.end(); ++ori) {
78      DatabaseIdentifier identifier =
79          DatabaseIdentifier::Parse(ori->GetOriginIdentifier());
80      if (!BrowsingDataHelper::HasWebScheme(identifier.ToOrigin())) {
81        // Non-websafe state is not considered browsing data.
82        continue;
83      }
84      std::vector<string16> databases;
85      ori->GetAllDatabaseNames(&databases);
86      for (std::vector<string16>::const_iterator db = databases.begin();
87           db != databases.end(); ++db) {
88        base::FilePath file_path =
89            tracker_->GetFullDBFilePath(ori->GetOriginIdentifier(), *db);
90        base::PlatformFileInfo file_info;
91        if (file_util::GetFileInfo(file_path, &file_info)) {
92          database_info_.push_back(DatabaseInfo(
93                identifier,
94                UTF16ToUTF8(*db),
95                UTF16ToUTF8(ori->GetDatabaseDescription(*db)),
96                file_info.size,
97                file_info.last_modified));
98        }
99      }
100    }
101  }
102
103  BrowserThread::PostTask(
104      BrowserThread::UI, FROM_HERE,
105      base::Bind(&BrowsingDataDatabaseHelper::NotifyInUIThread, this));
106}
107
108void BrowsingDataDatabaseHelper::NotifyInUIThread() {
109  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
110  DCHECK(is_fetching_);
111  completion_callback_.Run(database_info_);
112  completion_callback_.Reset();
113  is_fetching_ = false;
114  database_info_.clear();
115}
116
117void BrowsingDataDatabaseHelper::DeleteDatabaseOnFileThread(
118    const std::string& origin,
119    const std::string& name) {
120  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
121  if (!tracker_.get())
122    return;
123  tracker_->DeleteDatabase(origin, UTF8ToUTF16(name),
124                           net::CompletionCallback());
125}
126
127CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::PendingDatabaseInfo(
128    const GURL& origin,
129    const std::string& name,
130    const std::string& description)
131    : origin(origin),
132      name(name),
133      description(description) {
134}
135
136CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::~PendingDatabaseInfo() {}
137
138bool CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo::operator<(
139    const PendingDatabaseInfo& other) const {
140  if (origin == other.origin)
141    return name < other.name;
142  return origin < other.origin;
143}
144
145CannedBrowsingDataDatabaseHelper::CannedBrowsingDataDatabaseHelper(
146    Profile* profile)
147    : BrowsingDataDatabaseHelper(profile),
148      profile_(profile) {
149}
150
151CannedBrowsingDataDatabaseHelper* CannedBrowsingDataDatabaseHelper::Clone() {
152  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
153  CannedBrowsingDataDatabaseHelper* clone =
154      new CannedBrowsingDataDatabaseHelper(profile_);
155
156  clone->pending_database_info_ = pending_database_info_;
157  return clone;
158}
159
160void CannedBrowsingDataDatabaseHelper::AddDatabase(
161    const GURL& origin,
162    const std::string& name,
163    const std::string& description) {
164  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
165  if (BrowsingDataHelper::HasWebScheme(origin)) {
166    pending_database_info_.insert(PendingDatabaseInfo(
167          origin, name, description));
168  }
169}
170
171void CannedBrowsingDataDatabaseHelper::Reset() {
172  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
173  pending_database_info_.clear();
174}
175
176bool CannedBrowsingDataDatabaseHelper::empty() const {
177  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
178  return pending_database_info_.empty();
179}
180
181size_t CannedBrowsingDataDatabaseHelper::GetDatabaseCount() const {
182  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
183  return pending_database_info_.size();
184}
185
186const std::set<CannedBrowsingDataDatabaseHelper::PendingDatabaseInfo>&
187CannedBrowsingDataDatabaseHelper::GetPendingDatabaseInfo() {
188  return pending_database_info_;
189}
190
191void CannedBrowsingDataDatabaseHelper::StartFetching(
192    const base::Callback<void(const std::list<DatabaseInfo>&)>& callback) {
193  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
194  DCHECK(!is_fetching_);
195  DCHECK_EQ(false, callback.is_null());
196
197  is_fetching_ = true;
198  completion_callback_ = callback;
199
200  database_info_.clear();
201  for (std::set<PendingDatabaseInfo>::const_iterator
202       info = pending_database_info_.begin();
203       info != pending_database_info_.end(); ++info) {
204    DatabaseIdentifier identifier =
205        DatabaseIdentifier::CreateFromOrigin(info->origin);
206
207    database_info_.push_back(DatabaseInfo(
208        identifier,
209        info->name,
210        info->description,
211        0,
212        base::Time()));
213  }
214
215  BrowserThread::PostTask(
216      BrowserThread::UI, FROM_HERE,
217      base::Bind(&CannedBrowsingDataDatabaseHelper::NotifyInUIThread, this));
218}
219
220CannedBrowsingDataDatabaseHelper::~CannedBrowsingDataDatabaseHelper() {}
221