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

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

Issue 13392014: Move c/b/webdata/ code to components/webdata/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Pure merge Created 7 years, 8 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 "base/memory/scoped_vector.h"
10 #include "chrome/browser/api/webdata/web_data_results.h"
11 #include "chrome/browser/api/webdata/web_data_service_consumer.h"
12 #include "chrome/browser/webdata/web_data_request_manager.h"
13
14 using base::Bind;
15 using base::FilePath;
16 using content::BrowserThread;
17
18
19 ////////////////////////////////////////////////////////////////////////////////
20 //
21 // WebDataServiceBackend implementation.
22 //
23 ////////////////////////////////////////////////////////////////////////////////
24
25 // Refcounted to allow asynchronous destruction on the DB thread.
26 class WebDataServiceBackend
27 : public base::RefCountedThreadSafe<WebDataServiceBackend,
28 BrowserThread::DeleteOnDBThread> {
29 public:
30 explicit WebDataServiceBackend(const FilePath& path);
31
32 // Must call only before InitDatabaseWithCallback.
33 void AddTable(scoped_ptr<WebDatabaseTable> table);
34
35 // Initializes the database and notifies caller via callback when complete.
36 // Callback is called synchronously.
37 void InitDatabaseWithCallback(
38 const WebDatabaseService::InitCallback& callback);
39
40 // Opens the database file from the profile path if an init has not yet been
41 // attempted. Separated from the constructor to ease construction/destruction
42 // of this object on one thread but database access on the DB thread. Returns
43 // the status of the database.
44 sql::InitStatus LoadDatabaseIfNecessary();
45
46 // Shuts down database. |should_reinit| tells us whether or not it should be
47 // possible to re-initialize the DB after the shutdown.
48 void ShutdownDatabase(bool should_reinit);
49
50 // Task wrappers to run database tasks.
51 void DBWriteTaskWrapper(
52 const WebDatabaseService::WriteTask& task,
53 scoped_ptr<WebDataRequest> request);
54 void DBReadTaskWrapper(
55 const WebDatabaseService::ReadTask& task,
56 scoped_ptr<WebDataRequest> request);
57
58 const scoped_refptr<WebDataRequestManager>& request_manager() {
59 return request_manager_;
60 }
61
62 WebDatabase* database() { return db_.get(); }
63
64 private:
65 friend struct BrowserThread::DeleteOnThread<BrowserThread::DB>;
66 friend class base::DeleteHelper<WebDataServiceBackend>;
67
68 virtual ~WebDataServiceBackend();
69
70 // Commit the current transaction.
71 void Commit();
72
73 // Path to database file.
74 FilePath db_path_;
75
76 // The tables that participate in managing the database. These are
77 // owned here but other than that this class does nothing with
78 // them. Their initialization is in whatever factory creates
79 // WebDatabaseService, and lookup by type is provided by the
80 // WebDatabase class. The tables need to be owned by this refcounted
81 // object, or they themselves would need to be refcounted. Owning
82 // them here rather than having WebDatabase own them makes for
83 // easier unit testing of WebDatabase.
84 ScopedVector<WebDatabaseTable> tables_;
85
86 scoped_ptr<WebDatabase> db_;
87
88 // Keeps track of all pending requests made to the db.
89 scoped_refptr<WebDataRequestManager> request_manager_;
90
91 // State of database initialization. Used to prevent the executing of tasks
92 // before the db is ready.
93 sql::InitStatus init_status_;
94
95 // True if an attempt has been made to load the database (even if the attempt
96 // fails), used to avoid continually trying to reinit if the db init fails.
97 bool init_complete_;
98
99 DISALLOW_COPY_AND_ASSIGN(WebDataServiceBackend);
100 };
101
102 WebDataServiceBackend::WebDataServiceBackend(
103 const FilePath& path)
104 : db_path_(path),
105 request_manager_(new WebDataRequestManager()),
106 init_status_(sql::INIT_FAILURE),
107 init_complete_(false) {
108 }
109
110 void WebDataServiceBackend::AddTable(scoped_ptr<WebDatabaseTable> table) {
111 DCHECK(!db_.get());
112 tables_.push_back(table.release());
113 }
114
115 void WebDataServiceBackend::InitDatabaseWithCallback(
116 const WebDatabaseService::InitCallback& callback) {
117 if (!callback.is_null()) {
118 callback.Run(LoadDatabaseIfNecessary());
119 }
120 }
121
122 sql::InitStatus WebDataServiceBackend::LoadDatabaseIfNecessary() {
123 if (init_complete_ || db_path_.empty()) {
124 return init_status_;
125 }
126 init_complete_ = true;
127 db_.reset(new WebDatabase());
128
129 for (ScopedVector<WebDatabaseTable>::iterator it = tables_.begin();
130 it != tables_.end();
131 ++it) {
132 db_->AddTable(*it);
133 }
134
135 init_status_ = db_->Init(db_path_);
136 if (init_status_ != sql::INIT_OK) {
137 LOG(ERROR) << "Cannot initialize the web database: " << init_status_;
138 db_.reset(NULL);
139 return init_status_;
140 }
141
142 db_->BeginTransaction();
143 return init_status_;
144 }
145
146 void WebDataServiceBackend::ShutdownDatabase(bool should_reinit) {
147 if (db_ && init_status_ == sql::INIT_OK)
148 db_->CommitTransaction();
149 db_.reset(NULL);
150 init_complete_ = !should_reinit; // Setting init_complete_ to true will ensure
151 // that the init sequence is not re-run.
152
153 init_status_ = sql::INIT_FAILURE;
154 }
155
156 void WebDataServiceBackend::DBWriteTaskWrapper(
157 const WebDatabaseService::WriteTask& task,
158 scoped_ptr<WebDataRequest> request) {
159 LoadDatabaseIfNecessary();
160 if (db_ && init_status_ == sql::INIT_OK && !request->IsCancelled()) {
161 WebDatabase::State state = task.Run(db_.get());
162 if (state == WebDatabase::COMMIT_NEEDED)
163 Commit();
164 }
165 request_manager_->RequestCompleted(request.Pass());
166 }
167
168 void WebDataServiceBackend::DBReadTaskWrapper(
169 const WebDatabaseService::ReadTask& task,
170 scoped_ptr<WebDataRequest> request) {
171 LoadDatabaseIfNecessary();
172 if (db_ && init_status_ == sql::INIT_OK && !request->IsCancelled()) {
173 request->SetResult(task.Run(db_.get()).Pass());
174 }
175 request_manager_->RequestCompleted(request.Pass());
176 }
177
178 WebDataServiceBackend::~WebDataServiceBackend() {
179 ShutdownDatabase(false);
180 }
181
182 void WebDataServiceBackend::Commit() {
183 if (db_ && init_status_ == sql::INIT_OK) {
184 db_->CommitTransaction();
185 db_->BeginTransaction();
186 } else {
187 NOTREACHED() << "Commit scheduled after Shutdown()";
188 }
189 }
190
191 ////////////////////////////////////////////////////////////////////////////////
192 WebDatabaseService::WebDatabaseService(
193 const base::FilePath& path)
194 : path_(path) {
195 // WebDatabaseService should be instantiated on UI thread.
196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
197 // WebDatabaseService requires DB thread if instantiated.
198 DCHECK(BrowserThread::IsWellKnownThread(BrowserThread::DB));
199 }
200
201 WebDatabaseService::~WebDatabaseService() {
202 }
203
204 void WebDatabaseService::AddTable(scoped_ptr<WebDatabaseTable> table) {
205 if (!wds_backend_) {
206 wds_backend_ = new WebDataServiceBackend(path_);
207 }
208 wds_backend_->AddTable(table.Pass());
209 }
210
211 void WebDatabaseService::LoadDatabase(const InitCallback& callback) {
212 DCHECK(wds_backend_);
213
214 BrowserThread::PostTask(
215 BrowserThread::DB,
216 FROM_HERE,
217 Bind(&WebDataServiceBackend::InitDatabaseWithCallback,
218 wds_backend_, callback));
219 }
220
221 void WebDatabaseService::UnloadDatabase() {
222 if (!wds_backend_)
223 return;
224 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
225 Bind(&WebDataServiceBackend::ShutdownDatabase,
226 wds_backend_, true));
227 }
228
229 void WebDatabaseService::ShutdownDatabase() {
230 if (!wds_backend_)
231 return;
232 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
233 Bind(&WebDataServiceBackend::ShutdownDatabase,
234 wds_backend_, false));
235 }
236
237 WebDatabase* WebDatabaseService::GetDatabaseOnDB() const {
238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
239 if (!wds_backend_)
240 return NULL;
241 return wds_backend_->database();
242 }
243
244 void WebDatabaseService::ScheduleDBTask(
245 const tracked_objects::Location& from_here,
246 const WriteTask& task) {
247 if (!wds_backend_) {
248 NOTREACHED() << "Task scheduled after Shutdown()";
249 return;
250 }
251
252 scoped_ptr<WebDataRequest> request(
253 new WebDataRequest(NULL, wds_backend_->request_manager()));
254
255 BrowserThread::PostTask(BrowserThread::DB, from_here,
256 Bind(&WebDataServiceBackend::DBWriteTaskWrapper, wds_backend_,
257 task, base::Passed(&request)));
258 }
259
260 WebDataServiceBase::Handle WebDatabaseService::ScheduleDBTaskWithResult(
261 const tracked_objects::Location& from_here,
262 const ReadTask& task,
263 WebDataServiceConsumer* consumer) {
264 DCHECK(consumer);
265 WebDataServiceBase::Handle handle = 0;
266
267 if (!wds_backend_) {
268 NOTREACHED() << "Task scheduled after Shutdown()";
269 return handle;
270 }
271
272 scoped_ptr<WebDataRequest> request(
273 new WebDataRequest(consumer, wds_backend_->request_manager()));
274 handle = request->GetHandle();
275
276 BrowserThread::PostTask(BrowserThread::DB, from_here,
277 Bind(&WebDataServiceBackend::DBReadTaskWrapper, wds_backend_,
278 task, base::Passed(&request)));
279
280 return handle;
281 }
282
283 void WebDatabaseService::CancelRequest(WebDataServiceBase::Handle h) {
284 if (!wds_backend_)
285 return;
286 wds_backend_->request_manager()->CancelRequest(h);
287 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698