Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: chrome/browser/webdata/web_database_service.cc

Issue 12851008: Create a common base class for all the webdatas (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase on trunk and comments Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 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/webdata/web_database_service.h"
6
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "chrome/browser/api/webdata/web_data_results.h"
10 #include "chrome/browser/api/webdata/web_data_service_consumer.h"
11 #include "chrome/browser/webdata/web_data_request_manager.h"
12 #include "chrome/browser/webdata/web_data_service.h"
13 // TODO(caitkp): Remove this autofill dependency.
14 #include "components/autofill/browser/autofill_country.h"
15
16 using base::Bind;
17 using base::FilePath;
18 using content::BrowserThread;
19
20
21 ////////////////////////////////////////////////////////////////////////////////
22 //
23 // WebDataServiceBackend implementation.
24 //
25 ////////////////////////////////////////////////////////////////////////////////
26
27 // Refcounted to allow asynchronous destruction on the DB thread.
28 class WebDataServiceBackend
29 : public base::RefCountedThreadSafe<WebDataServiceBackend,
30 BrowserThread::DeleteOnDBThread> {
31 public:
32 explicit WebDataServiceBackend(const FilePath& path);
33
34 // Initializes the database and notifies caller via callback when complete.
35 // Callback is called synchronously.
36 void InitDatabaseWithCallback(
37 const WebDatabaseService::InitCallback& callback);
38
39 // Opens the database file from the profile path if an init has not yet been
40 // attempted. Separated from the constructor to ease construction/destruction
41 // of this object on one thread but database access on the DB thread. Returns
42 // the status of the database.
43 sql::InitStatus LoadDatabaseIfNecessary();
44
45 // Shuts down database. |should_reinit| tells us whether or not it should be
46 // possible to re-initialize the DB after the shutdown.
47 void ShutdownDatabase(bool should_reinit);
48
49 // Task wrappers to run database tasks.
50 void DBWriteTaskWrapper(
51 const WebDatabaseService::WriteTask& task,
52 scoped_ptr<WebDataRequest> request);
53 void DBReadTaskWrapper(
54 const WebDatabaseService::ReadTask& task,
55 scoped_ptr<WebDataRequest> request);
56
57 const scoped_refptr<WebDataRequestManager>& request_manager() {
58 return request_manager_;
59 }
60
61 WebDatabase* database() { return db_.get(); }
62
63 private:
64 friend struct BrowserThread::DeleteOnThread<BrowserThread::DB>;
65 friend class base::DeleteHelper<WebDataServiceBackend>;
66
67 virtual ~WebDataServiceBackend();
68
69 // Commit the current transaction.
70 void Commit();
71
72 // Path to database file.
73 FilePath db_path_;
74
75 scoped_ptr<WebDatabase> db_;
76
77 // Keeps track of all pending requests made to the db.
78 scoped_refptr<WebDataRequestManager> request_manager_;
79
80 // State of database initialization. Used to prevent the executing of tasks
81 // before the db is ready.
82 sql::InitStatus init_status_;
83
84 // True if an attempt has been made to load the database (even if the attempt
85 // fails), used to avoid continually trying to reinit if the db init fails.
86 bool init_complete_;
87
88 // The application locale. The locale is needed for some database migrations,
89 // and must be read on the UI thread. It's cached here so that we can pass it
90 // to the migration code on the DB thread.
91 const std::string app_locale_;
92
93 DISALLOW_COPY_AND_ASSIGN(WebDataServiceBackend);
94 };
95
96 WebDataServiceBackend::WebDataServiceBackend(const FilePath& path)
97 : db_path_(path),
98 request_manager_(new WebDataRequestManager()),
99 init_status_(sql::INIT_FAILURE),
100 init_complete_(false),
101 app_locale_(AutofillCountry::ApplicationLocale()) {
102 }
103
104 void WebDataServiceBackend::InitDatabaseWithCallback(
105 const WebDatabaseService::InitCallback& callback) {
106 if (!callback.is_null()) {
107 callback.Run(LoadDatabaseIfNecessary());
108 }
109 }
110
111 sql::InitStatus WebDataServiceBackend::LoadDatabaseIfNecessary() {
112 if (init_complete_ || db_path_.empty()) {
113 return init_status_;
114 }
115 init_complete_ = true;
116 db_.reset(new WebDatabase());
117 init_status_ = db_->Init(db_path_, app_locale_);
118 if (init_status_ != sql::INIT_OK) {
119 LOG(ERROR) << "Cannot initialize the web database: " << init_status_;
120 db_.reset(NULL);
121 return init_status_;
122 }
123
124 db_->BeginTransaction();
125 return init_status_;
126 }
127
128 void WebDataServiceBackend::ShutdownDatabase(bool should_reinit) {
129 if (db_ && init_status_ == sql::INIT_OK)
130 db_->CommitTransaction();
131 db_.reset(NULL);
132 init_complete_ = !should_reinit; // Setting init_complete_ to true will ensure
133 // that the init sequence is not re-run.
134
135 init_status_ = sql::INIT_FAILURE;
136 }
137
138 void WebDataServiceBackend::DBWriteTaskWrapper(
139 const WebDatabaseService::WriteTask& task,
140 scoped_ptr<WebDataRequest> request) {
141 LoadDatabaseIfNecessary();
142 if (db_ && init_status_ == sql::INIT_OK && !request->IsCancelled()) {
143 WebDatabase::State state = task.Run(db_.get());
144 if (state == WebDatabase::COMMIT_NEEDED)
145 Commit();
146 }
147 request_manager_->RequestCompleted(request.Pass());
148 }
149
150 void WebDataServiceBackend::DBReadTaskWrapper(
151 const WebDatabaseService::ReadTask& task,
152 scoped_ptr<WebDataRequest> request) {
153 LoadDatabaseIfNecessary();
154 if (db_ && init_status_ == sql::INIT_OK && !request->IsCancelled()) {
155 request->SetResult(task.Run(db_.get()).Pass());
156 }
157 request_manager_->RequestCompleted(request.Pass());
158 }
159
160 WebDataServiceBackend::~WebDataServiceBackend() {
161 ShutdownDatabase(false);
162 }
163
164 void WebDataServiceBackend::Commit() {
165 if (db_ && init_status_ == sql::INIT_OK) {
166 db_->CommitTransaction();
167 db_->BeginTransaction();
168 } else {
169 NOTREACHED() << "Commit scheduled after Shutdown()";
170 }
171 }
172
173 ////////////////////////////////////////////////////////////////////////////////
174 WebDatabaseService::WebDatabaseService(const base::FilePath& path)
175 : path_(path) {
176 // WebDatabaseService should be instantiated on UI thread.
177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
178 // WebDatabaseService requires DB thread if instantiated.
179 DCHECK(BrowserThread::IsWellKnownThread(BrowserThread::DB));
180 }
181
182 WebDatabaseService::~WebDatabaseService() {
183 }
184
185 void WebDatabaseService::LoadDatabase(const InitCallback& callback) {
186 if (!wds_backend_)
187 wds_backend_ = new WebDataServiceBackend(path_);
188
189 BrowserThread::PostTask(
190 BrowserThread::DB,
191 FROM_HERE,
192 Bind(&WebDataServiceBackend::InitDatabaseWithCallback,
193 wds_backend_, callback));
194 }
195
196 void WebDatabaseService::UnloadDatabase() {
197 if (!wds_backend_)
198 return;
199 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
200 Bind(&WebDataServiceBackend::ShutdownDatabase,
201 wds_backend_, true));
202 }
203
204 void WebDatabaseService::ShutdownDatabase() {
205 if (!wds_backend_)
206 return;
207 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
208 Bind(&WebDataServiceBackend::ShutdownDatabase,
209 wds_backend_, false));
210 }
211
212 WebDatabase* WebDatabaseService::GetDatabaseOnDB() const {
213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
214 if (!wds_backend_)
215 return NULL;
216 return wds_backend_->database();
217 }
218
219 void WebDatabaseService::ScheduleDBTask(
220 const tracked_objects::Location& from_here,
221 const WriteTask& task) {
222 if (!wds_backend_) {
223 NOTREACHED() << "Task scheduled after Shutdown()";
224 return;
225 }
226
227 scoped_ptr<WebDataRequest> request(
228 new WebDataRequest(NULL, wds_backend_->request_manager()));
229
230 BrowserThread::PostTask(BrowserThread::DB, from_here,
231 Bind(&WebDataServiceBackend::DBWriteTaskWrapper, wds_backend_,
232 task, base::Passed(&request)));
233 }
234
235 WebDataService::Handle WebDatabaseService::ScheduleDBTaskWithResult(
236 const tracked_objects::Location& from_here,
237 const ReadTask& task,
238 WebDataServiceConsumer* consumer) {
239 DCHECK(consumer);
240 WebDataService::Handle handle = 0;
241
242 if (!wds_backend_) {
243 NOTREACHED() << "Task scheduled after Shutdown()";
244 return handle;
245 }
246
247 scoped_ptr<WebDataRequest> request(
248 new WebDataRequest(consumer, wds_backend_->request_manager()));
249 handle = request->GetHandle();
250
251 BrowserThread::PostTask(BrowserThread::DB, from_here,
252 Bind(&WebDataServiceBackend::DBReadTaskWrapper, wds_backend_,
253 task, base::Passed(&request)));
254
255 return handle;
256 }
257
258 void WebDatabaseService::CancelRequest(WebDataServiceBase::Handle h) {
259 if (!wds_backend_)
260 return;
261 wds_backend_->request_manager()->CancelRequest(h);
262 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698