1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "components/webdata/common/web_database_service.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/location.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "components/webdata/common/web_data_request_manager.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "components/webdata/common/web_data_results.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "components/webdata/common/web_data_service_backend.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "components/webdata/common/web_data_service_consumer.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::Bind;
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::FilePath;
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Receives messages from the backend on the DB thread, posts them to
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// WebDatabaseService on the UI thread.
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class WebDatabaseService::BackendDelegate :
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public WebDataServiceBackend::Delegate {
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BackendDelegate(
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const base::WeakPtr<WebDatabaseService>& web_database_service)
247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      : web_database_service_(web_database_service),
257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        callback_thread_(base::MessageLoopProxy::current()) {
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void DBLoaded(sql::InitStatus status) OVERRIDE {
297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    callback_thread_->PostTask(
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        FROM_HERE,
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&WebDatabaseService::OnDatabaseLoadDone,
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   web_database_service_,
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   status));
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::WeakPtr<WebDatabaseService> web_database_service_;
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> callback_thread_;
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)WebDatabaseService::WebDatabaseService(
417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const base::FilePath& path,
427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const scoped_refptr<base::MessageLoopProxy>& ui_thread,
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const scoped_refptr<base::MessageLoopProxy>& db_thread)
447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : base::RefCountedDeleteOnMessageLoop<WebDatabaseService>(ui_thread),
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      path_(path),
467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      db_loaded_(false),
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      db_thread_(db_thread),
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      weak_ptr_factory_(this) {
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // WebDatabaseService should be instantiated on UI thread.
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(ui_thread->BelongsToCurrentThread());
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // WebDatabaseService requires DB thread if instantiated.
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(db_thread.get());
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)WebDatabaseService::~WebDatabaseService() {
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebDatabaseService::AddTable(scoped_ptr<WebDatabaseTable> table) {
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!wds_backend_) {
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    wds_backend_ = new WebDataServiceBackend(
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        path_, new BackendDelegate(weak_ptr_factory_.GetWeakPtr()),
627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        db_thread_);
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  wds_backend_->AddTable(table.Pass());
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebDatabaseService::LoadDatabase() {
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(wds_backend_);
697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  db_thread_->PostTask(
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&WebDataServiceBackend::InitDatabase, wds_backend_));
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebDatabaseService::ShutdownDatabase() {
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  db_loaded_ = false;
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  loaded_callbacks_.clear();
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error_callbacks_.clear();
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  weak_ptr_factory_.InvalidateWeakPtrs();
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!wds_backend_)
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  db_thread_->PostTask(
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FROM_HERE, Bind(&WebDataServiceBackend::ShutdownDatabase, wds_backend_));
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)WebDatabase* WebDatabaseService::GetDatabaseOnDB() const {
867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(db_thread_->BelongsToCurrentThread());
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return wds_backend_ ? wds_backend_->database() : NULL;
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
90a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)scoped_refptr<WebDataServiceBackend> WebDatabaseService::GetBackend() const {
91a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return wds_backend_;
92a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
93a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebDatabaseService::ScheduleDBTask(
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const tracked_objects::Location& from_here,
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const WriteTask& task) {
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(wds_backend_);
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<WebDataRequest> request(
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new WebDataRequest(NULL, wds_backend_->request_manager().get()));
1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  db_thread_->PostTask(from_here,
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       Bind(&WebDataServiceBackend::DBWriteTaskWrapper,
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            wds_backend_, task, base::Passed(&request)));
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)WebDataServiceBase::Handle WebDatabaseService::ScheduleDBTaskWithResult(
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const tracked_objects::Location& from_here,
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ReadTask& task,
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebDataServiceConsumer* consumer) {
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(consumer);
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(wds_backend_);
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<WebDataRequest> request(
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new WebDataRequest(consumer, wds_backend_->request_manager().get()));
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebDataServiceBase::Handle handle = request->GetHandle();
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  db_thread_->PostTask(from_here,
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       Bind(&WebDataServiceBackend::DBReadTaskWrapper,
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            wds_backend_, task, base::Passed(&request)));
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return handle;
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebDatabaseService::CancelRequest(WebDataServiceBase::Handle h) {
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!wds_backend_)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  wds_backend_->request_manager()->CancelRequest(h);
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void WebDatabaseService::RegisterDBLoadedCallback(
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const DBLoadedCallback& callback) {
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  loaded_callbacks_.push_back(callback);
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void WebDatabaseService::RegisterDBErrorCallback(
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const DBLoadErrorCallback& callback) {
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error_callbacks_.push_back(callback);
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebDatabaseService::OnDatabaseLoadDone(sql::InitStatus status) {
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status == sql::INIT_OK) {
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    db_loaded_ = true;
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (size_t i = 0; i < loaded_callbacks_.size(); i++) {
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!loaded_callbacks_[i].is_null())
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        loaded_callbacks_[i].Run();
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    loaded_callbacks_.clear();
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Notify that the database load failed.
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (size_t i = 0; i < error_callbacks_.size(); i++) {
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!error_callbacks_[i].is_null())
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        error_callbacks_[i].Run(status);
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    error_callbacks_.clear();
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
156