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();
     49        ++it) {
     50     db_->AddTable(*it);
     51   }
     52 
     53   init_status_ = db_->Init(db_path_);
     54   if (init_status_ != sql::INIT_OK) {
     55     LOG(ERROR) << "Cannot initialize the web database: " << init_status_;
     56     db_.reset(NULL);
     57     return init_status_;
     58   }
     59 
     60   db_->BeginTransaction();
     61   return init_status_;
     62 }
     63 
     64 void WebDataServiceBackend::ShutdownDatabase(bool should_reinit) {
     65   if (db_ && init_status_ == sql::INIT_OK)
     66     db_->CommitTransaction();
     67   db_.reset(NULL);
     68   init_complete_ = !should_reinit; // Setting init_complete_ to true will ensure
     69   // that the init sequence is not re-run.
     70 
     71   init_status_ = sql::INIT_FAILURE;
     72 }
     73 
     74 void WebDataServiceBackend::DBWriteTaskWrapper(
     75     const WebDatabaseService::WriteTask& task,
     76     scoped_ptr<WebDataRequest> request) {
     77   if (request->IsCancelled())
     78     return;
     79 
     80   ExecuteWriteTask(task);
     81   request_manager_->RequestCompleted(request.Pass());
     82 }
     83 
     84 void WebDataServiceBackend::ExecuteWriteTask(
     85     const WebDatabaseService::WriteTask& task) {
     86   LoadDatabaseIfNecessary();
     87   if (db_ && init_status_ == sql::INIT_OK) {
     88     WebDatabase::State state = task.Run(db_.get());
     89     if (state == WebDatabase::COMMIT_NEEDED)
     90       Commit();
     91   }
     92 }
     93 
     94 void WebDataServiceBackend::DBReadTaskWrapper(
     95     const WebDatabaseService::ReadTask& task,
     96     scoped_ptr<WebDataRequest> request) {
     97   if (request->IsCancelled())
     98     return;
     99 
    100   request->SetResult(ExecuteReadTask(task).Pass());
    101   request_manager_->RequestCompleted(request.Pass());
    102 }
    103 
    104 scoped_ptr<WDTypedResult> WebDataServiceBackend::ExecuteReadTask(
    105     const WebDatabaseService::ReadTask& task) {
    106   LoadDatabaseIfNecessary();
    107   if (db_ && init_status_ == sql::INIT_OK) {
    108     return task.Run(db_.get());
    109   }
    110   return scoped_ptr<WDTypedResult>();
    111 }
    112 
    113 WebDataServiceBackend::~WebDataServiceBackend() {
    114   ShutdownDatabase(false);
    115 }
    116 
    117 void WebDataServiceBackend::Commit() {
    118   if (db_ && init_status_ == sql::INIT_OK) {
    119     db_->CommitTransaction();
    120     db_->BeginTransaction();
    121   } else {
    122     NOTREACHED() << "Commit scheduled after Shutdown()";
    123   }
    124 }
    125