Home | History | Annotate | Download | only in common
      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 "components/webdata/common/web_data_service_backend.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/location.h"
      9 #include "components/webdata/common/web_data_request_manager.h"
     10 #include "components/webdata/common/web_database.h"
     11 #include "components/webdata/common/web_database_table.h"
     12 
     13 using base::Bind;
     14 using base::FilePath;
     15 
     16 WebDataServiceBackend::WebDataServiceBackend(
     17     const FilePath& path,
     18     Delegate* delegate,
     19     const scoped_refptr<base::MessageLoopProxy>& db_thread)
     20     : base::RefCountedDeleteOnMessageLoop<WebDataServiceBackend>(db_thread),
     21       db_path_(path),
     22       request_manager_(new WebDataRequestManager()),
     23       init_status_(sql::INIT_FAILURE),
     24       init_complete_(false),
     25       delegate_(delegate) {
     26 }
     27 
     28 void WebDataServiceBackend::AddTable(scoped_ptr<WebDatabaseTable> table) {
     29   DCHECK(!db_.get());
     30   tables_.push_back(table.release());
     31 }
     32 
     33 void WebDataServiceBackend::InitDatabase() {
     34   LoadDatabaseIfNecessary();
     35   if (delegate_) {
     36     delegate_->DBLoaded(init_status_);
     37   }
     38 }
     39 
     40 sql::InitStatus WebDataServiceBackend::LoadDatabaseIfNecessary() {
     41   if (init_complete_ || db_path_.empty()) {
     42     return init_status_;
     43   }
     44   init_complete_ = true;
     45   db_.reset(new WebDatabase());
     46 
     47   for (ScopedVector<WebDatabaseTable>::iterator it = tables_.begin();
     48        it != tables_.end(); ++it) {
     49     db_->AddTable(*it);
     50   }
     51 
     52   init_status_ = db_->Init(db_path_);
     53   if (init_status_ != sql::INIT_OK) {
     54     LOG(ERROR) << "Cannot initialize the web database: " << init_status_;
     55     db_.reset(NULL);
     56     return init_status_;
     57   }
     58 
     59   db_->BeginTransaction();
     60   return init_status_;
     61 }
     62 
     63 void WebDataServiceBackend::ShutdownDatabase() {
     64   if (db_ && init_status_ == sql::INIT_OK)
     65     db_->CommitTransaction();
     66   db_.reset(NULL);
     67   init_complete_ = true;  // Ensures the init sequence is not re-run.
     68   init_status_ = sql::INIT_FAILURE;
     69 }
     70 
     71 void WebDataServiceBackend::DBWriteTaskWrapper(
     72     const WebDatabaseService::WriteTask& task,
     73     scoped_ptr<WebDataRequest> request) {
     74   if (request->IsCancelled())
     75     return;
     76 
     77   ExecuteWriteTask(task);
     78   request_manager_->RequestCompleted(request.Pass());
     79 }
     80 
     81 void WebDataServiceBackend::ExecuteWriteTask(
     82     const WebDatabaseService::WriteTask& task) {
     83   LoadDatabaseIfNecessary();
     84   if (db_ && init_status_ == sql::INIT_OK) {
     85     WebDatabase::State state = task.Run(db_.get());
     86     if (state == WebDatabase::COMMIT_NEEDED)
     87       Commit();
     88   }
     89 }
     90 
     91 void WebDataServiceBackend::DBReadTaskWrapper(
     92     const WebDatabaseService::ReadTask& task,
     93     scoped_ptr<WebDataRequest> request) {
     94   if (request->IsCancelled())
     95     return;
     96 
     97   request->SetResult(ExecuteReadTask(task).Pass());
     98   request_manager_->RequestCompleted(request.Pass());
     99 }
    100 
    101 scoped_ptr<WDTypedResult> WebDataServiceBackend::ExecuteReadTask(
    102     const WebDatabaseService::ReadTask& task) {
    103   LoadDatabaseIfNecessary();
    104   if (db_ && init_status_ == sql::INIT_OK) {
    105     return task.Run(db_.get());
    106   }
    107   return scoped_ptr<WDTypedResult>();
    108 }
    109 
    110 WebDataServiceBackend::~WebDataServiceBackend() {
    111   ShutdownDatabase();
    112 }
    113 
    114 void WebDataServiceBackend::Commit() {
    115   DCHECK(db_);
    116   DCHECK_EQ(sql::INIT_OK, init_status_);
    117   db_->CommitTransaction();
    118   db_->BeginTransaction();
    119 }
    120