web_database_service.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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),
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      weak_ptr_factory_(this),
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      db_loaded_(false),
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      db_thread_(db_thread) {
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) {
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!wds_backend_.get()) {
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() {
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(wds_backend_.get());
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  db_thread_->PostTask(
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&WebDataServiceBackend::InitDatabase, wds_backend_));
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebDatabaseService::UnloadDatabase() {
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  db_loaded_ = false;
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!wds_backend_.get())
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  db_thread_->PostTask(FROM_HERE,
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&WebDataServiceBackend::ShutdownDatabase,
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           wds_backend_, true));
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebDatabaseService::ShutdownDatabase() {
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  db_loaded_ = false;
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  weak_ptr_factory_.InvalidateWeakPtrs();
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  loaded_callbacks_.clear();
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error_callbacks_.clear();
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!wds_backend_.get())
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  db_thread_->PostTask(FROM_HERE,
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&WebDataServiceBackend::ShutdownDatabase,
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           wds_backend_, false));
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)WebDatabase* WebDatabaseService::GetDatabaseOnDB() const {
977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(db_thread_->BelongsToCurrentThread());
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!wds_backend_.get())
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return NULL;
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return wds_backend_->database();
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
103a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)scoped_refptr<WebDataServiceBackend> WebDatabaseService::GetBackend() const {
104a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return wds_backend_;
105a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
106a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebDatabaseService::ScheduleDBTask(
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const tracked_objects::Location& from_here,
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const WriteTask& task) {
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!wds_backend_.get()) {
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    NOTREACHED() << "Task scheduled after Shutdown()";
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<WebDataRequest> request(
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new WebDataRequest(NULL, wds_backend_->request_manager().get()));
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  db_thread_->PostTask(from_here,
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&WebDataServiceBackend::DBWriteTaskWrapper, wds_backend_,
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           task, base::Passed(&request)));
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)WebDataServiceBase::Handle WebDatabaseService::ScheduleDBTaskWithResult(
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const tracked_objects::Location& from_here,
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ReadTask& task,
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebDataServiceConsumer* consumer) {
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(consumer);
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  WebDataServiceBase::Handle handle = 0;
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!wds_backend_.get()) {
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    NOTREACHED() << "Task scheduled after Shutdown()";
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return handle;
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<WebDataRequest> request(
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new WebDataRequest(consumer, wds_backend_->request_manager().get()));
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  handle = request->GetHandle();
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  db_thread_->PostTask(from_here,
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&WebDataServiceBackend::DBReadTaskWrapper, wds_backend_,
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           task, base::Passed(&request)));
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return handle;
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebDatabaseService::CancelRequest(WebDataServiceBase::Handle h) {
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!wds_backend_.get())
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  wds_backend_->request_manager()->CancelRequest(h);
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void WebDatabaseService::RegisterDBLoadedCallback(
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const DBLoadedCallback& callback) {
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  loaded_callbacks_.push_back(callback);
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void WebDatabaseService::RegisterDBErrorCallback(
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const DBLoadErrorCallback& callback) {
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error_callbacks_.push_back(callback);
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebDatabaseService::OnDatabaseLoadDone(sql::InitStatus status) {
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status == sql::INIT_OK) {
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    db_loaded_ = true;
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (size_t i = 0; i < loaded_callbacks_.size(); i++) {
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!loaded_callbacks_[i].is_null())
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        loaded_callbacks_[i].Run();
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    loaded_callbacks_.clear();
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Notify that the database load failed.
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (size_t i = 0; i < error_callbacks_.size(); i++) {
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!error_callbacks_[i].is_null())
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        error_callbacks_[i].Run(status);
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    error_callbacks_.clear();
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
182