summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcaitkp@chromium.org <caitkp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-19 03:18:46 +0000
committercaitkp@chromium.org <caitkp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-19 03:18:46 +0000
commit8b390a6d541c0e0700f795d7a76e21ac168f4ab9 (patch)
treee3260779d27281c9f508fcafd7f3633b17be7ce8
parentd7e70c88f9a98b0475fdd9860c162cd54c0b9692 (diff)
downloadchromium_src-8b390a6d541c0e0700f795d7a76e21ac168f4ab9.zip
chromium_src-8b390a6d541c0e0700f795d7a76e21ac168f4ab9.tar.gz
chromium_src-8b390a6d541c0e0700f795d7a76e21ac168f4ab9.tar.bz2
Second try at splitting WebDataService (minus ownership changes)
Split Database handling into a separate class, but keep it owned by WebDataService, to avoid it disappearing out from under us (crbug.com/181628). TBR=ben@chromium.org,sky@chromium.org TEST= unit_tests BUG=181277 COLLABORATOR=joi@chromium.org Review URL: https://chromiumcodereview.appspot.com/12871006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188935 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/password_manager/password_store_win_unittest.cc3
-rw-r--r--chrome/browser/search_engines/template_url_service_test_util.cc116
-rw-r--r--chrome/browser/search_engines/template_url_service_test_util.h6
-rw-r--r--chrome/browser/search_engines/template_url_service_unittest.cc3
-rw-r--r--chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc4
-rw-r--r--chrome/browser/webdata/web_data_service.cc512
-rw-r--r--chrome/browser/webdata/web_data_service.h195
-rw-r--r--chrome/browser/webdata/web_data_service_factory.cc3
-rw-r--r--chrome/browser/webdata/web_data_service_unittest.cc5
-rw-r--r--chrome/browser/webdata/web_data_service_win.cc36
-rw-r--r--chrome/browser/webdata/web_database.h4
-rw-r--r--chrome/browser/webdata/web_database_service.cc262
-rw-r--r--chrome/browser/webdata/web_database_service.h94
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/test/base/testing_profile.cc4
15 files changed, 726 insertions, 523 deletions
diff --git a/chrome/browser/password_manager/password_store_win_unittest.cc b/chrome/browser/password_manager/password_store_win_unittest.cc
index 2528ba5..af88968 100644
--- a/chrome/browser/password_manager/password_store_win_unittest.cc
+++ b/chrome/browser/password_manager/password_store_win_unittest.cc
@@ -115,7 +115,8 @@ class PasswordStoreWinTest : public testing::Test {
ASSERT_TRUE(login_db_->Init(temp_dir_.path().Append(
FILE_PATH_LITERAL("login_test"))));
wds_ = new WebDataService();
- ASSERT_TRUE(wds_->Init(temp_dir_.path()));
+ base::FilePath path = temp_dir_.path().AppendASCII("web_data_test");
+ wds_->Init(path);
}
virtual void TearDown() {
diff --git a/chrome/browser/search_engines/template_url_service_test_util.cc b/chrome/browser/search_engines/template_url_service_test_util.cc
index 244046e..ba19b0a 100644
--- a/chrome/browser/search_engines/template_url_service_test_util.cc
+++ b/chrome/browser/search_engines/template_url_service_test_util.cc
@@ -5,7 +5,6 @@
#include "chrome/browser/search_engines/template_url_service_test_util.h"
#include "base/bind.h"
-#include "base/files/scoped_temp_dir.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/synchronization/waitable_event.h"
@@ -53,35 +52,6 @@ static void WaitForThreadToProcessRequests(BrowserThread::ID identifier) {
} // namespace
-// Subclass the TestingProfile so that it can return a WebDataService.
-class TemplateURLServiceTestingProfile : public TestingProfile {
- public:
- TemplateURLServiceTestingProfile()
- : TestingProfile(),
- db_thread_(BrowserThread::DB),
- io_thread_(BrowserThread::IO) {
- }
-
- void SetUp();
- void TearDown();
-
- // Starts the I/O thread. This isn't done automatically because not every test
- // needs this.
- void StartIOThread() {
- io_thread_.StartIOThread();
- }
-
- static scoped_refptr<RefcountedProfileKeyedService>
- GetWebDataServiceForTemplateURLServiceTestingProfile(Profile* profile);
-
- private:
- scoped_refptr<WebDataService> service_;
- base::ScopedTempDir temp_dir_;
- content::TestBrowserThread db_thread_;
- content::TestBrowserThread io_thread_;
-};
-
-
// Trivial subclass of TemplateURLService that records the last invocation of
// SetKeywordSearchTermsForURL.
class TestingTemplateURLService : public TemplateURLService {
@@ -113,21 +83,38 @@ class TestingTemplateURLService : public TemplateURLService {
DISALLOW_COPY_AND_ASSIGN(TestingTemplateURLService);
};
-void TemplateURLServiceTestingProfile::SetUp() {
+TemplateURLServiceTestUtil::TemplateURLServiceTestUtil()
+ : ui_thread_(BrowserThread::UI, &message_loop_),
+ db_thread_(BrowserThread::DB),
+ io_thread_(BrowserThread::IO),
+ changed_count_(0) {
+}
+
+TemplateURLServiceTestUtil::~TemplateURLServiceTestUtil() {
+}
+
+void TemplateURLServiceTestUtil::SetUp() {
+ profile_.reset(new TestingProfile());
db_thread_.Start();
+ profile_->CreateWebDataService();
- // Make unique temp directory.
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ TemplateURLService* service = static_cast<TemplateURLService*>(
+ TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+ profile_.get(), TestingTemplateURLService::Build));
+ service->AddObserver(this);
- base::FilePath path = temp_dir_.path().AppendASCII("TestDataService.db");
- service_ = new WebDataService;
- ASSERT_TRUE(service_->InitWithPath(path));
+#if defined(OS_CHROMEOS)
+ google_util::chromeos::ClearBrandForCurrentSession();
+#endif
}
-void TemplateURLServiceTestingProfile::TearDown() {
- // Clear the request context so it will get deleted. This should be done
- // before shutting down the I/O thread to avoid memory leaks.
- ResetRequestContext();
+void TemplateURLServiceTestUtil::TearDown() {
+ if (profile_.get()) {
+ // Clear the request context so it will get deleted. This should be done
+ // before shutting down the I/O thread to avoid memory leaks.
+ profile_->ResetRequestContext();
+ profile_.reset();
+ }
// Wait for the delete of the request context to happen.
if (io_thread_.IsRunning())
@@ -136,11 +123,6 @@ void TemplateURLServiceTestingProfile::TearDown() {
// The I/O thread must be shutdown before the DB thread.
io_thread_.Stop();
- // Clean up the test directory.
- if (service_.get()) {
- service_->ShutdownOnUIThread();
- service_ = NULL;
- }
// Note that we must ensure the DB thread is stopped after WDS
// shutdown (so it can commit pending transactions) but before
// deleting the test profile directory, otherwise we may not be
@@ -151,47 +133,10 @@ void TemplateURLServiceTestingProfile::TearDown() {
BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done)));
done.Wait();
+ MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+ MessageLoop::current()->Run();
db_thread_.Stop();
-}
-
-scoped_refptr<RefcountedProfileKeyedService>
-TemplateURLServiceTestingProfile::
- GetWebDataServiceForTemplateURLServiceTestingProfile(Profile* profile) {
- TemplateURLServiceTestingProfile* test_profile =
- reinterpret_cast<TemplateURLServiceTestingProfile*>(profile);
- return test_profile->service_;
-}
-
-TemplateURLServiceTestUtil::TemplateURLServiceTestUtil()
- : ui_thread_(BrowserThread::UI, &message_loop_),
- changed_count_(0) {
-}
-
-TemplateURLServiceTestUtil::~TemplateURLServiceTestUtil() {
-}
-
-void TemplateURLServiceTestUtil::SetUp() {
- profile_.reset(new TemplateURLServiceTestingProfile());
- WebDataServiceFactory::GetInstance()->SetTestingFactory(
- profile_.get(), TemplateURLServiceTestingProfile::
- GetWebDataServiceForTemplateURLServiceTestingProfile);
- profile_->SetUp();
- TemplateURLService* service = static_cast<TemplateURLService*>(
- TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
- profile_.get(), TestingTemplateURLService::Build));
- service->AddObserver(this);
-
-#if defined(OS_CHROMEOS)
- google_util::chromeos::ClearBrandForCurrentSession();
-#endif
-}
-
-void TemplateURLServiceTestUtil::TearDown() {
- if (profile_.get()) {
- profile_->TearDown();
- profile_.reset();
- }
UIThreadSearchTermsData::SetGoogleBaseURL(std::string());
// Flush the message loop to make application verifiers happy.
@@ -233,6 +178,7 @@ void TemplateURLServiceTestUtil::ChangeModelToLoadState() {
model()->service_ = WebDataServiceFactory::GetForProfile(
profile_.get(), Profile::EXPLICIT_ACCESS);
+ BlockTillServiceProcessesRequests();
}
void TemplateURLServiceTestUtil::ClearModel() {
@@ -330,7 +276,7 @@ TestingProfile* TemplateURLServiceTestUtil::profile() const {
}
void TemplateURLServiceTestUtil::StartIOThread() {
- profile_->StartIOThread();
+ io_thread_.StartIOThread();
}
void TemplateURLServiceTestUtil::PumpLoop() {
diff --git a/chrome/browser/search_engines/template_url_service_test_util.h b/chrome/browser/search_engines/template_url_service_test_util.h
index ae4fe36..f903e26 100644
--- a/chrome/browser/search_engines/template_url_service_test_util.h
+++ b/chrome/browser/search_engines/template_url_service_test_util.h
@@ -18,7 +18,7 @@
class GURL;
class TemplateURLService;
-class TemplateURLServiceTestingProfile;
+class TestingProfile;
class TestingTemplateURLService;
class TestingProfile;
class WebDataService;
@@ -112,7 +112,9 @@ class TemplateURLServiceTestUtil : public TemplateURLServiceObserver {
// Needed to make the DeleteOnUIThread trait of WebDataService work
// properly.
content::TestBrowserThread ui_thread_;
- scoped_ptr<TemplateURLServiceTestingProfile> profile_;
+ content::TestBrowserThread db_thread_;
+ content::TestBrowserThread io_thread_;
+ scoped_ptr<TestingProfile> profile_;
int changed_count_;
DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceTestUtil);
diff --git a/chrome/browser/search_engines/template_url_service_unittest.cc b/chrome/browser/search_engines/template_url_service_unittest.cc
index 8c35473..9adafe7 100644
--- a/chrome/browser/search_engines/template_url_service_unittest.cc
+++ b/chrome/browser/search_engines/template_url_service_unittest.cc
@@ -1311,8 +1311,7 @@ TEST_F(TemplateURLServiceTest, FailedInit) {
scoped_refptr<WebDataService> web_service =
WebDataServiceFactory::GetForProfile(test_util_.profile(),
Profile::EXPLICIT_ACCESS);
- web_service->UnloadDatabase();
- web_service->set_failed_init(true);
+ web_service->ShutdownDatabase();
test_util_.ResetModel(false);
model()->Load();
diff --git a/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc b/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc
index b7cbb3e..978c329 100644
--- a/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc
@@ -128,7 +128,6 @@ TEST_F(SyncSearchEngineDataTypeControllerTest, StartURLServiceNotReady) {
WillOnce(MakeSharedChangeProcessor());
EXPECT_CALL(model_load_callback_, Run(_, _));
-
EXPECT_FALSE(syncable_service_.syncing());
search_engine_dtc_->LoadModels(
base::Bind(&ModelLoadCallbackMock::Run,
@@ -142,6 +141,9 @@ TEST_F(SyncSearchEngineDataTypeControllerTest, StartURLServiceNotReady) {
content::Source<TemplateURLService>(test_util_.model()),
content::NotificationService::NoDetails());
EXPECT_EQ(DataTypeController::MODEL_LOADED, search_engine_dtc_->state());
+
+ // Wait until WebDB is loaded before we shut it down.
+ test_util_.BlockTillServiceProcessesRequests();
}
TEST_F(SyncSearchEngineDataTypeControllerTest, StartFirstRun) {
diff --git a/chrome/browser/webdata/web_data_service.cc b/chrome/browser/webdata/web_data_service.cc
index c5976af..edf8827 100644
--- a/chrome/browser/webdata/web_data_service.cc
+++ b/chrome/browser/webdata/web_data_service.cc
@@ -22,7 +22,7 @@
#include "chrome/browser/webdata/logins_table.h"
#include "chrome/browser/webdata/token_service_table.h"
#include "chrome/browser/webdata/web_apps_table.h"
-#include "chrome/browser/webdata/web_database.h"
+#include "chrome/browser/webdata/web_database_service.h"
#include "chrome/browser/webdata/web_intents_table.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_notification_types.h"
@@ -78,15 +78,9 @@ WDKeywordsResult::WDKeywordsResult()
WDKeywordsResult::~WDKeywordsResult() {}
WebDataService::WebDataService()
- : is_running_(false),
- db_(NULL),
- request_manager_(new WebDataRequestManager()),
- app_locale_(AutofillCountry::ApplicationLocale()),
+ : db_loaded_(false),
autocomplete_syncable_service_(NULL),
- autofill_profile_syncable_service_(NULL),
- failed_init_(false),
- should_commit_(false),
- main_loop_(MessageLoop::current()) {
+ autofill_profile_syncable_service_(NULL) {
// WebDataService requires DB thread if instantiated.
// Set WebDataServiceFactory::GetInstance()->SetTestingFactory(&profile, NULL)
// if you do not want to instantiate WebDataService in your test.
@@ -108,27 +102,36 @@ void WebDataService::NotifyOfMultipleAutofillChanges(
}
void WebDataService::ShutdownOnUIThread() {
- ScheduleTask(FROM_HERE,
- Bind(&WebDataService::ShutdownSyncableServices, this));
- UnloadDatabase();
+ db_loaded_ = false;
+ ShutdownDatabase();
+ BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
+ Bind(&WebDataService::ShutdownSyncableServices, this));
}
-bool WebDataService::Init(const base::FilePath& profile_path) {
- base::FilePath path = profile_path;
- path = path.Append(chrome::kWebDataFilename);
- return InitWithPath(path);
-}
+void WebDataService::Init(const base::FilePath& path) {
+ wdbs_.reset(new WebDatabaseService(path));
+ wdbs_->LoadDatabase(Bind(&WebDataService::DatabaseInitOnDB, this));
-bool WebDataService::IsRunning() const {
- return is_running_;
+ BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
+ Bind(&WebDataService::InitializeSyncableServices, this));
}
void WebDataService::UnloadDatabase() {
- ScheduleTask(FROM_HERE, Bind(&WebDataService::ShutdownDatabase, this));
+ if (!wdbs_)
+ return;
+ wdbs_->UnloadDatabase();
+}
+
+void WebDataService::ShutdownDatabase() {
+ if (!wdbs_)
+ return;
+ wdbs_->ShutdownDatabase();
}
void WebDataService::CancelRequest(Handle h) {
- request_manager_->CancelRequest(h);
+ if (!wdbs_)
+ return;
+ wdbs_->CancelRequest(h);
}
content::NotificationSource WebDataService::GetNotificationSource() {
@@ -136,12 +139,13 @@ content::NotificationSource WebDataService::GetNotificationSource() {
}
bool WebDataService::IsDatabaseLoaded() {
- return db_ != NULL;
+ return db_loaded_;
}
WebDatabase* WebDataService::GetDatabase() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- return db_;
+ if (!wdbs_)
+ return NULL;
+ return wdbs_->GetDatabaseOnDB();
}
//////////////////////////////////////////////////////////////////////////////
@@ -151,34 +155,34 @@ WebDatabase* WebDataService::GetDatabase() {
//////////////////////////////////////////////////////////////////////////////
void WebDataService::AddKeyword(const TemplateURLData& data) {
- ScheduleDBTask(
+ wdbs_->ScheduleDBTask(
FROM_HERE, Bind(&WebDataService::AddKeywordImpl, this, data));
}
void WebDataService::RemoveKeyword(TemplateURLID id) {
- ScheduleDBTask(
+ wdbs_->ScheduleDBTask(
FROM_HERE, Bind(&WebDataService::RemoveKeywordImpl, this, id));
}
void WebDataService::UpdateKeyword(const TemplateURLData& data) {
- ScheduleDBTask(
+ wdbs_->ScheduleDBTask(
FROM_HERE, Bind(&WebDataService::UpdateKeywordImpl, this, data));
}
WebDataService::Handle WebDataService::GetKeywords(
WebDataServiceConsumer* consumer) {
- return ScheduleDBTaskWithResult(FROM_HERE,
+ return wdbs_->ScheduleDBTaskWithResult(FROM_HERE,
Bind(&WebDataService::GetKeywordsImpl, this), consumer);
}
void WebDataService::SetDefaultSearchProvider(const TemplateURL* url) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::SetDefaultSearchProviderImpl, this,
url ? url->id() : 0));
}
void WebDataService::SetBuiltinKeywordVersion(int version) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::SetBuiltinKeywordVersionImpl, this, version));
}
@@ -190,26 +194,25 @@ void WebDataService::SetBuiltinKeywordVersion(int version) {
void WebDataService::SetWebAppImage(const GURL& app_url,
const SkBitmap& image) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::SetWebAppImageImpl, this, app_url, image));
}
void WebDataService::SetWebAppHasAllImages(const GURL& app_url,
bool has_all_images) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::SetWebAppHasAllImagesImpl, this, app_url,
has_all_images));
}
void WebDataService::RemoveWebApp(const GURL& app_url) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::RemoveWebAppImpl, this, app_url));
}
WebDataService::Handle WebDataService::GetWebAppImages(
- const GURL& app_url,
- WebDataServiceConsumer* consumer) {
- return ScheduleDBTaskWithResult(FROM_HERE,
+ const GURL& app_url, WebDataServiceConsumer* consumer) {
+ return wdbs_->ScheduleDBTaskWithResult(FROM_HERE,
Bind(&WebDataService::GetWebAppImagesImpl, this, app_url), consumer);
}
@@ -221,18 +224,19 @@ WebDataService::Handle WebDataService::GetWebAppImages(
void WebDataService::SetTokenForService(const std::string& service,
const std::string& token) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::SetTokenForServiceImpl, this, service, token));
}
void WebDataService::RemoveAllTokens() {
- ScheduleDBTask(FROM_HERE, Bind(&WebDataService::RemoveAllTokensImpl, this));
+ wdbs_->ScheduleDBTask(FROM_HERE,
+ Bind(&WebDataService::RemoveAllTokensImpl, this));
}
// Null on failure. Success is WDResult<std::string>
WebDataService::Handle WebDataService::GetAllTokens(
WebDataServiceConsumer* consumer) {
- return ScheduleDBTaskWithResult(FROM_HERE,
+ return wdbs_->ScheduleDBTaskWithResult(FROM_HERE,
Bind(&WebDataService::GetAllTokensImpl, this), consumer);
}
@@ -244,145 +248,125 @@ WebDataService::Handle WebDataService::GetAllTokens(
void WebDataService::AddFormFields(
const std::vector<FormFieldData>& fields) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::AddFormElementsImpl, this, fields));
}
WebDataService::Handle WebDataService::GetFormValuesForElementName(
const string16& name, const string16& prefix, int limit,
WebDataServiceConsumer* consumer) {
- return ScheduleDBTaskWithResult(FROM_HERE,
+ return wdbs_->ScheduleDBTaskWithResult(FROM_HERE,
Bind(&WebDataService::GetFormValuesForElementNameImpl,
- this, name, prefix, limit),
- consumer);
+ this, name, prefix, limit), consumer);
}
void WebDataService::RemoveFormElementsAddedBetween(const Time& delete_begin,
const Time& delete_end) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::RemoveFormElementsAddedBetweenImpl,
this, delete_begin, delete_end));
}
void WebDataService::RemoveExpiredFormElements() {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::RemoveExpiredFormElementsImpl, this));
}
void WebDataService::RemoveFormValueForElementName(
const string16& name, const string16& value) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::RemoveFormValueForElementNameImpl,
this, name, value));
}
void WebDataService::AddAutofillProfile(const AutofillProfile& profile) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::AddAutofillProfileImpl, this, profile));
}
void WebDataService::UpdateAutofillProfile(const AutofillProfile& profile) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::UpdateAutofillProfileImpl, this, profile));
}
void WebDataService::RemoveAutofillProfile(const std::string& guid) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::RemoveAutofillProfileImpl, this, guid));
}
WebDataService::Handle WebDataService::GetAutofillProfiles(
WebDataServiceConsumer* consumer) {
- return ScheduleDBTaskWithResult(FROM_HERE,
+ return wdbs_->ScheduleDBTaskWithResult(FROM_HERE,
Bind(&WebDataService::GetAutofillProfilesImpl, this), consumer);
}
void WebDataService::AddCreditCard(const CreditCard& credit_card) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::AddCreditCardImpl, this, credit_card));
}
void WebDataService::UpdateCreditCard(const CreditCard& credit_card) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::UpdateCreditCardImpl, this, credit_card));
}
void WebDataService::RemoveCreditCard(const std::string& guid) {
- ScheduleDBTask(FROM_HERE,
+ wdbs_->ScheduleDBTask(FROM_HERE,
Bind(&WebDataService::RemoveCreditCardImpl, this, guid));
}
WebDataService::Handle WebDataService::GetCreditCards(
WebDataServiceConsumer* consumer) {
- return ScheduleDBTaskWithResult(FROM_HERE,
+ return wdbs_->ScheduleDBTaskWithResult(FROM_HERE,
Bind(&WebDataService::GetCreditCardsImpl, this), consumer);
}
void WebDataService::RemoveAutofillProfilesAndCreditCardsModifiedBetween(
const Time& delete_begin,
const Time& delete_end) {
- ScheduleDBTask(FROM_HERE, Bind(
+ wdbs_->ScheduleDBTask(FROM_HERE, Bind(
&WebDataService::RemoveAutofillProfilesAndCreditCardsModifiedBetweenImpl,
this, delete_begin, delete_end));
}
WebDataService::~WebDataService() {
- if (is_running_ && db_) {
- NOTREACHED() << "WebDataService dtor called without Shutdown";
- }
-}
-
-bool WebDataService::InitWithPath(const base::FilePath& path) {
- path_ = path;
- is_running_ = true;
-
- ScheduleTask(FROM_HERE,
- Bind(&WebDataService::InitializeDatabaseIfNecessary, this));
- ScheduleTask(FROM_HERE,
- Bind(&WebDataService::InitializeSyncableServices, this));
- return true;
+ wdbs_.reset();
+ DCHECK(!autocomplete_syncable_service_);
+ DCHECK(!autofill_profile_syncable_service_);
}
////////////////////////////////////////////////////////////////////////////////
//
-// The following methods are executed in Chrome_WebDataThread.
+// The following methods are executed on the DB thread.
//
////////////////////////////////////////////////////////////////////////////////
-void WebDataService::DBInitFailed(sql::InitStatus init_status) {
+void WebDataService::DBInitFailed(sql::InitStatus sql_status) {
ShowProfileErrorDialog(
- (init_status == sql::INIT_FAILURE) ?
+ (sql_status == sql::INIT_FAILURE) ?
IDS_COULDNT_OPEN_PROFILE_ERROR : IDS_PROFILE_TOO_NEW_ERROR);
}
-void WebDataService::InitializeDatabaseIfNecessary() {
- if (db_ || failed_init_ || path_.empty())
- return;
+void WebDataService::NotifyDatabaseLoadedOnUIThread() {
+ db_loaded_ = true;
+ // Notify that the database has been initialized.
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_WEB_DATABASE_LOADED,
+ content::Source<WebDataService>(this),
+ content::NotificationService::NoDetails());
+}
- // In the rare case where the db fails to initialize a dialog may get shown
- // that blocks the caller, yet allows other messages through. For this reason
- // we only set db_ to the created database if creation is successful. That
- // way other methods won't do anything as db_ is still NULL.
- WebDatabase* db = new WebDatabase();
- sql::InitStatus init_status = db->Init(path_, app_locale_);
- if (init_status != sql::INIT_OK) {
- LOG(ERROR) << "Cannot initialize the web database: " << init_status;
- failed_init_ = true;
- delete db;
- if (main_loop_) {
- main_loop_->PostTask(
- FROM_HERE,
- base::Bind(&WebDataService::DBInitFailed, this, init_status));
- }
- return;
+void WebDataService::DatabaseInitOnDB(sql::InitStatus status) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ if (status == sql::INIT_OK) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&WebDataService::NotifyDatabaseLoadedOnUIThread, this));
+ } else {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&WebDataService::DBInitFailed, this, status));
}
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&WebDataService::NotifyDatabaseLoadedOnUIThread, this));
-
- db_ = db;
- db_->BeginTransaction();
}
void WebDataService::InitializeSyncableServices() {
@@ -394,24 +378,6 @@ void WebDataService::InitializeSyncableServices() {
autofill_profile_syncable_service_ = new AutofillProfileSyncableService(this);
}
-void WebDataService::NotifyDatabaseLoadedOnUIThread() {
- // Notify that the database has been initialized.
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_WEB_DATABASE_LOADED,
- content::Source<WebDataService>(this),
- content::NotificationService::NoDetails());
-}
-
-void WebDataService::ShutdownDatabase() {
- should_commit_ = false;
-
- if (db_) {
- db_->CommitTransaction();
- delete db_;
- db_ = NULL;
- }
-}
-
void WebDataService::ShutdownSyncableServices() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
@@ -421,132 +387,61 @@ void WebDataService::ShutdownSyncableServices() {
autofill_profile_syncable_service_ = NULL;
}
-void WebDataService::Commit() {
- if (should_commit_) {
- should_commit_ = false;
-
- if (db_) {
- db_->CommitTransaction();
- db_->BeginTransaction();
- }
- }
-}
-
-void WebDataService::ScheduleTask(const tracked_objects::Location& from_here,
- const base::Closure& task) {
- if (is_running_)
- BrowserThread::PostTask(BrowserThread::DB, from_here, task);
- else
- NOTREACHED() << "Task scheduled after Shutdown()";
-}
-
-void WebDataService::ScheduleDBTask(
- const tracked_objects::Location& from_here,
- const base::Closure& task) {
- scoped_ptr<WebDataRequest> request(
- new WebDataRequest(NULL, request_manager_.get()));
- if (is_running_) {
- BrowserThread::PostTask(BrowserThread::DB, from_here,
- base::Bind(&WebDataService::DBTaskWrapper, this, task,
- base::Passed(&request)));
- } else {
- NOTREACHED() << "Task scheduled after Shutdown()";
- }
-}
-
-WebDataService::Handle WebDataService::ScheduleDBTaskWithResult(
- const tracked_objects::Location& from_here,
- const ResultTask& task,
- WebDataServiceConsumer* consumer) {
- DCHECK(consumer);
- scoped_ptr<WebDataRequest> request(
- new WebDataRequest(consumer, request_manager_.get()));
- WebDataService::Handle handle = request->GetHandle();
- if (is_running_) {
- BrowserThread::PostTask(BrowserThread::DB, from_here,
- base::Bind(&WebDataService::DBResultTaskWrapper, this, task,
- base::Passed(&request)));
- } else {
- NOTREACHED() << "Task scheduled after Shutdown()";
- }
- return handle;
-}
-
-void WebDataService::DBTaskWrapper(const base::Closure& task,
- scoped_ptr<WebDataRequest> request) {
- InitializeDatabaseIfNecessary();
- if (db_ && !request->IsCancelled()) {
- task.Run();
- }
- request_manager_->RequestCompleted(request.Pass());
-}
-
-void WebDataService::DBResultTaskWrapper(const ResultTask& task,
- scoped_ptr<WebDataRequest> request) {
- InitializeDatabaseIfNecessary();
- if (db_ && !request->IsCancelled()) {
- request->SetResult(task.Run());
- }
- request_manager_->RequestCompleted(request.Pass());
-}
-
-void WebDataService::ScheduleCommit() {
- if (should_commit_ == false) {
- should_commit_ = true;
- ScheduleTask(FROM_HERE, Bind(&WebDataService::Commit, this));
- }
-}
-
////////////////////////////////////////////////////////////////////////////////
//
// Keywords implementation.
//
////////////////////////////////////////////////////////////////////////////////
-void WebDataService::AddKeywordImpl(const TemplateURLData& data) {
- db_->GetKeywordTable()->AddKeyword(data);
- ScheduleCommit();
+WebDatabase::State WebDataService::AddKeywordImpl(
+ const TemplateURLData& data, WebDatabase* db) {
+ db->GetKeywordTable()->AddKeyword(data);
+ return WebDatabase::COMMIT_NEEDED;
}
-void WebDataService::RemoveKeywordImpl(TemplateURLID id) {
+WebDatabase::State WebDataService::RemoveKeywordImpl(
+ TemplateURLID id, WebDatabase* db) {
DCHECK(id);
- db_->GetKeywordTable()->RemoveKeyword(id);
- ScheduleCommit();
+ db->GetKeywordTable()->RemoveKeyword(id);
+ return WebDatabase::COMMIT_NEEDED;
}
-void WebDataService::UpdateKeywordImpl(const TemplateURLData& data) {
- if (!db_->GetKeywordTable()->UpdateKeyword(data)) {
+WebDatabase::State WebDataService::UpdateKeywordImpl(
+ const TemplateURLData& data, WebDatabase* db) {
+ if (!db->GetKeywordTable()->UpdateKeyword(data)) {
NOTREACHED();
- return;
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
- ScheduleCommit();
+ return WebDatabase::COMMIT_NEEDED;
}
-scoped_ptr<WDTypedResult> WebDataService::GetKeywordsImpl() {
+scoped_ptr<WDTypedResult> WebDataService::GetKeywordsImpl(WebDatabase* db) {
WDKeywordsResult result;
- db_->GetKeywordTable()->GetKeywords(&result.keywords);
+ db->GetKeywordTable()->GetKeywords(&result.keywords);
result.default_search_provider_id =
- db_->GetKeywordTable()->GetDefaultSearchProviderID();
+ db->GetKeywordTable()->GetDefaultSearchProviderID();
result.builtin_keyword_version =
- db_->GetKeywordTable()->GetBuiltinKeywordVersion();
+ db->GetKeywordTable()->GetBuiltinKeywordVersion();
return scoped_ptr<WDTypedResult>(
new WDResult<WDKeywordsResult>(KEYWORDS_RESULT, result));
}
-void WebDataService::SetDefaultSearchProviderImpl(TemplateURLID id) {
- if (!db_->GetKeywordTable()->SetDefaultSearchProviderID(id)) {
+WebDatabase::State WebDataService::SetDefaultSearchProviderImpl(
+ TemplateURLID id, WebDatabase* db) {
+ if (!db->GetKeywordTable()->SetDefaultSearchProviderID(id)) {
NOTREACHED();
- return;
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
- ScheduleCommit();
+ return WebDatabase::COMMIT_NEEDED;
}
-void WebDataService::SetBuiltinKeywordVersionImpl(int version) {
- if (!db_->GetKeywordTable()->SetBuiltinKeywordVersion(version)) {
+WebDatabase::State WebDataService::SetBuiltinKeywordVersionImpl(
+ int version, WebDatabase* db) {
+ if (!db->GetKeywordTable()->SetBuiltinKeywordVersion(version)) {
NOTREACHED();
- return;
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
- ScheduleCommit();
+ return WebDatabase::COMMIT_NEEDED;
}
////////////////////////////////////////////////////////////////////////////////
@@ -555,29 +450,30 @@ void WebDataService::SetBuiltinKeywordVersionImpl(int version) {
//
////////////////////////////////////////////////////////////////////////////////
-void WebDataService::SetWebAppImageImpl(
- const GURL& app_url, const SkBitmap& image) {
- db_->GetWebAppsTable()->SetWebAppImage(app_url, image);
- ScheduleCommit();
+WebDatabase::State WebDataService::SetWebAppImageImpl(
+ const GURL& app_url, const SkBitmap& image, WebDatabase* db) {
+ db->GetWebAppsTable()->SetWebAppImage(app_url, image);
+ return WebDatabase::COMMIT_NEEDED;
}
-void WebDataService::SetWebAppHasAllImagesImpl(
- const GURL& app_url, bool has_all_images) {
- db_->GetWebAppsTable()->SetWebAppHasAllImages(app_url, has_all_images);
- ScheduleCommit();
+WebDatabase::State WebDataService::SetWebAppHasAllImagesImpl(
+ const GURL& app_url, bool has_all_images, WebDatabase* db) {
+ db->GetWebAppsTable()->
+ SetWebAppHasAllImages(app_url, has_all_images);
+ return WebDatabase::COMMIT_NEEDED;
}
-void WebDataService::RemoveWebAppImpl(const GURL& app_url) {
- db_->GetWebAppsTable()->RemoveWebApp(app_url);
- ScheduleCommit();
+WebDatabase::State WebDataService::RemoveWebAppImpl(
+ const GURL& app_url, WebDatabase* db) {
+ db->GetWebAppsTable()->RemoveWebApp(app_url);
+ return WebDatabase::COMMIT_NEEDED;
}
scoped_ptr<WDTypedResult> WebDataService::GetWebAppImagesImpl(
- const GURL& app_url) {
+ const GURL& app_url, WebDatabase* db) {
WDAppImagesResult result;
- result.has_all_images =
- db_->GetWebAppsTable()->GetWebAppHasAllImages(app_url);
- db_->GetWebAppsTable()->GetWebAppImages(app_url, &result.images);
+ result.has_all_images = db->GetWebAppsTable()->GetWebAppHasAllImages(app_url);
+ db->GetWebAppsTable()->GetWebAppImages(app_url, &result.images);
return scoped_ptr<WDTypedResult>(
new WDResult<WDAppImagesResult>(WEB_APP_IMAGES, result));
}
@@ -588,22 +484,24 @@ scoped_ptr<WDTypedResult> WebDataService::GetWebAppImagesImpl(
//
////////////////////////////////////////////////////////////////////////////////
-void WebDataService::RemoveAllTokensImpl() {
- if (db_->GetTokenServiceTable()->RemoveAllTokens()) {
- ScheduleCommit();
+WebDatabase::State WebDataService::RemoveAllTokensImpl(WebDatabase* db) {
+ if (db->GetTokenServiceTable()->RemoveAllTokens()) {
+ return WebDatabase::COMMIT_NEEDED;
}
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
-void WebDataService::SetTokenForServiceImpl(const std::string& service,
- const std::string& token) {
- if (db_->GetTokenServiceTable()->SetTokenForService(service, token)) {
- ScheduleCommit();
+WebDatabase::State WebDataService::SetTokenForServiceImpl(
+ const std::string& service, const std::string& token, WebDatabase* db) {
+ if (db->GetTokenServiceTable()->SetTokenForService(service, token)) {
+ return WebDatabase::COMMIT_NEEDED;
}
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
-scoped_ptr<WDTypedResult> WebDataService::GetAllTokensImpl() {
+scoped_ptr<WDTypedResult> WebDataService::GetAllTokensImpl(WebDatabase* db) {
std::map<std::string, std::string> map;
- db_->GetTokenServiceTable()->GetAllTokens(&map);
+ db->GetTokenServiceTable()->GetAllTokens(&map);
return scoped_ptr<WDTypedResult>(
new WDResult<std::map<std::string, std::string> >(TOKEN_RESULT, map));
}
@@ -614,14 +512,13 @@ scoped_ptr<WDTypedResult> WebDataService::GetAllTokensImpl() {
//
////////////////////////////////////////////////////////////////////////////////
-void WebDataService::AddFormElementsImpl(
- const std::vector<FormFieldData>& fields) {
+WebDatabase::State WebDataService::AddFormElementsImpl(
+ const std::vector<FormFieldData>& fields, WebDatabase* db) {
AutofillChangeList changes;
- if (!db_->GetAutofillTable()->AddFormFieldValues(fields, &changes)) {
+ if (!db->GetAutofillTable()->AddFormFieldValues(fields, &changes)) {
NOTREACHED();
- return;
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
- ScheduleCommit();
// Post the notifications including the list of affected keys.
// This is sent here so that work resulting from this notification will be
@@ -630,21 +527,25 @@ void WebDataService::AddFormElementsImpl(
chrome::NOTIFICATION_AUTOFILL_ENTRIES_CHANGED,
content::Source<WebDataService>(this),
content::Details<AutofillChangeList>(&changes));
+
+ return WebDatabase::COMMIT_NEEDED;
}
scoped_ptr<WDTypedResult> WebDataService::GetFormValuesForElementNameImpl(
- const string16& name, const string16& prefix, int limit) {
+ const string16& name, const string16& prefix, int limit, WebDatabase* db) {
std::vector<string16> values;
- db_->GetAutofillTable()->GetFormValuesForElementName(
+ db->GetAutofillTable()->GetFormValuesForElementName(
name, prefix, &values, limit);
return scoped_ptr<WDTypedResult>(
new WDResult<std::vector<string16> >(AUTOFILL_VALUE_RESULT, values));
}
-void WebDataService::RemoveFormElementsAddedBetweenImpl(
- const base::Time& delete_begin, const base::Time& delete_end) {
+WebDatabase::State WebDataService::RemoveFormElementsAddedBetweenImpl(
+ const base::Time& delete_begin, const base::Time& delete_end,
+ WebDatabase* db) {
AutofillChangeList changes;
- if (db_->GetAutofillTable()->RemoveFormElementsAddedBetween(
+
+ if (db->GetAutofillTable()->RemoveFormElementsAddedBetween(
delete_begin, delete_end, &changes)) {
if (!changes.empty()) {
// Post the notifications including the list of affected keys.
@@ -655,14 +556,16 @@ void WebDataService::RemoveFormElementsAddedBetweenImpl(
content::Source<WebDataService>(this),
content::Details<AutofillChangeList>(&changes));
}
- ScheduleCommit();
+ return WebDatabase::COMMIT_NEEDED;
}
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
-void WebDataService::RemoveExpiredFormElementsImpl() {
+WebDatabase::State WebDataService::RemoveExpiredFormElementsImpl(
+ WebDatabase* db) {
AutofillChangeList changes;
- if (db_->GetAutofillTable()->RemoveExpiredFormElements(&changes)) {
+ if (db->GetAutofillTable()->RemoveExpiredFormElements(&changes)) {
if (!changes.empty()) {
// Post the notifications including the list of affected keys.
// This is sent here so that work resulting from this notification
@@ -672,33 +575,36 @@ void WebDataService::RemoveExpiredFormElementsImpl() {
content::Source<WebDataService>(this),
content::Details<AutofillChangeList>(&changes));
}
- ScheduleCommit();
+ return WebDatabase::COMMIT_NEEDED;
}
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
-void WebDataService::RemoveFormValueForElementNameImpl(
- const string16& name, const string16& value) {
+WebDatabase::State WebDataService::RemoveFormValueForElementNameImpl(
+ const string16& name, const string16& value, WebDatabase* db) {
- if (db_->GetAutofillTable()->RemoveFormElement(name, value)) {
+ if (db->GetAutofillTable()->RemoveFormElement(name, value)) {
AutofillChangeList changes;
changes.push_back(AutofillChange(AutofillChange::REMOVE,
AutofillKey(name, value)));
- ScheduleCommit();
// Post the notifications including the list of affected keys.
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_AUTOFILL_ENTRIES_CHANGED,
content::Source<WebDataService>(this),
content::Details<AutofillChangeList>(&changes));
+
+ return WebDatabase::COMMIT_NEEDED;
}
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
-void WebDataService::AddAutofillProfileImpl(const AutofillProfile& profile) {
- if (!db_->GetAutofillTable()->AddAutofillProfile(profile)) {
+WebDatabase::State WebDataService::AddAutofillProfileImpl(
+ const AutofillProfile& profile, WebDatabase* db) {
+ if (!db->GetAutofillTable()->AddAutofillProfile(profile)) {
NOTREACHED();
- return;
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
- ScheduleCommit();
// Send GUID-based notification.
AutofillProfileChange change(AutofillProfileChange::ADD,
@@ -707,24 +613,26 @@ void WebDataService::AddAutofillProfileImpl(const AutofillProfile& profile) {
chrome::NOTIFICATION_AUTOFILL_PROFILE_CHANGED,
content::Source<WebDataService>(this),
content::Details<AutofillProfileChange>(&change));
+
+ return WebDatabase::COMMIT_NEEDED;
}
-void WebDataService::UpdateAutofillProfileImpl(const AutofillProfile& profile) {
+WebDatabase::State WebDataService::UpdateAutofillProfileImpl(
+ const AutofillProfile& profile, WebDatabase* db) {
// Only perform the update if the profile exists. It is currently
// valid to try to update a missing profile. We simply drop the write and
// the caller will detect this on the next refresh.
AutofillProfile* original_profile = NULL;
- if (!db_->GetAutofillTable()->GetAutofillProfile(profile.guid(),
- &original_profile)) {
- return;
+ if (!db->GetAutofillTable()->GetAutofillProfile(profile.guid(),
+ &original_profile)) {
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
scoped_ptr<AutofillProfile> scoped_profile(original_profile);
- if (!db_->GetAutofillTable()->UpdateAutofillProfileMulti(profile)) {
+ if (!db->GetAutofillTable()->UpdateAutofillProfileMulti(profile)) {
NOTREACHED();
- return;
+ return WebDatabase::COMMIT_NEEDED;
}
- ScheduleCommit();
// Send GUID-based notification.
AutofillProfileChange change(AutofillProfileChange::UPDATE,
@@ -733,21 +641,23 @@ void WebDataService::UpdateAutofillProfileImpl(const AutofillProfile& profile) {
chrome::NOTIFICATION_AUTOFILL_PROFILE_CHANGED,
content::Source<WebDataService>(this),
content::Details<AutofillProfileChange>(&change));
+
+ return WebDatabase::COMMIT_NEEDED;
}
-void WebDataService::RemoveAutofillProfileImpl(const std::string& guid) {
+WebDatabase::State WebDataService::RemoveAutofillProfileImpl(
+ const std::string& guid, WebDatabase* db) {
AutofillProfile* profile = NULL;
- if (!db_->GetAutofillTable()->GetAutofillProfile(guid, &profile)) {
+ if (!db->GetAutofillTable()->GetAutofillProfile(guid, &profile)) {
NOTREACHED();
- return;
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
scoped_ptr<AutofillProfile> scoped_profile(profile);
- if (!db_->GetAutofillTable()->RemoveAutofillProfile(guid)) {
+ if (!db->GetAutofillTable()->RemoveAutofillProfile(guid)) {
NOTREACHED();
- return;
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
- ScheduleCommit();
// Send GUID-based notification.
AutofillProfileChange change(AutofillProfileChange::REMOVE, guid, NULL);
@@ -755,11 +665,14 @@ void WebDataService::RemoveAutofillProfileImpl(const std::string& guid) {
chrome::NOTIFICATION_AUTOFILL_PROFILE_CHANGED,
content::Source<WebDataService>(this),
content::Details<AutofillProfileChange>(&change));
+
+ return WebDatabase::COMMIT_NEEDED;
}
-scoped_ptr<WDTypedResult> WebDataService::GetAutofillProfilesImpl() {
+scoped_ptr<WDTypedResult> WebDataService::GetAutofillProfilesImpl(
+ WebDatabase* db) {
std::vector<AutofillProfile*> profiles;
- db_->GetAutofillTable()->GetAutofillProfiles(&profiles);
+ db->GetAutofillTable()->GetAutofillProfiles(&profiles);
return scoped_ptr<WDTypedResult>(
new WDDestroyableResult<std::vector<AutofillProfile*> >(
AUTOFILL_PROFILES_RESULT,
@@ -768,42 +681,46 @@ scoped_ptr<WDTypedResult> WebDataService::GetAutofillProfilesImpl() {
base::Unretained(this))));
}
-void WebDataService::AddCreditCardImpl(const CreditCard& credit_card) {
- if (!db_->GetAutofillTable()->AddCreditCard(credit_card)) {
+WebDatabase::State WebDataService::AddCreditCardImpl(
+ const CreditCard& credit_card, WebDatabase* db) {
+ if (!db->GetAutofillTable()->AddCreditCard(credit_card)) {
NOTREACHED();
- return;
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
- ScheduleCommit();
+
+ return WebDatabase::COMMIT_NEEDED;
}
-void WebDataService::UpdateCreditCardImpl(const CreditCard& credit_card) {
+WebDatabase::State WebDataService::UpdateCreditCardImpl(
+ const CreditCard& credit_card, WebDatabase* db) {
// It is currently valid to try to update a missing profile. We simply drop
// the write and the caller will detect this on the next refresh.
CreditCard* original_credit_card = NULL;
- if (!db_->GetAutofillTable()->GetCreditCard(credit_card.guid(),
- &original_credit_card)) {
- return;
+ if (!db->GetAutofillTable()->GetCreditCard(credit_card.guid(),
+ &original_credit_card)) {
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
scoped_ptr<CreditCard> scoped_credit_card(original_credit_card);
- if (!db_->GetAutofillTable()->UpdateCreditCard(credit_card)) {
+ if (!db->GetAutofillTable()->UpdateCreditCard(credit_card)) {
NOTREACHED();
- return;
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
- ScheduleCommit();
+ return WebDatabase::COMMIT_NEEDED;
}
-void WebDataService::RemoveCreditCardImpl(const std::string& guid) {
- if (!db_->GetAutofillTable()->RemoveCreditCard(guid)) {
+WebDatabase::State WebDataService::RemoveCreditCardImpl(
+ const std::string& guid, WebDatabase* db) {
+ if (!db->GetAutofillTable()->RemoveCreditCard(guid)) {
NOTREACHED();
- return;
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
- ScheduleCommit();
+ return WebDatabase::COMMIT_NEEDED;
}
-scoped_ptr<WDTypedResult> WebDataService::GetCreditCardsImpl() {
+scoped_ptr<WDTypedResult> WebDataService::GetCreditCardsImpl(WebDatabase* db) {
std::vector<CreditCard*> credit_cards;
- db_->GetAutofillTable()->GetCreditCards(&credit_cards);
+ db->GetAutofillTable()->GetCreditCards(&credit_cards);
return scoped_ptr<WDTypedResult>(
new WDDestroyableResult<std::vector<CreditCard*> >(
AUTOFILL_CREDITCARDS_RESULT,
@@ -812,11 +729,13 @@ scoped_ptr<WDTypedResult> WebDataService::GetCreditCardsImpl() {
base::Unretained(this))));
}
-void WebDataService::RemoveAutofillProfilesAndCreditCardsModifiedBetweenImpl(
- const base::Time& delete_begin, const base::Time& delete_end) {
+WebDatabase::State
+WebDataService::RemoveAutofillProfilesAndCreditCardsModifiedBetweenImpl(
+ const base::Time& delete_begin, const base::Time& delete_end,
+ WebDatabase* db) {
std::vector<std::string> profile_guids;
std::vector<std::string> credit_card_guids;
- if (db_->GetAutofillTable()->
+ if (db->GetAutofillTable()->
RemoveAutofillProfilesAndCreditCardsModifiedBetween(
delete_begin,
delete_end,
@@ -833,8 +752,9 @@ void WebDataService::RemoveAutofillProfilesAndCreditCardsModifiedBetweenImpl(
}
// Note: It is the caller's responsibility to post notifications for any
// changes, e.g. by calling the Refresh() method of PersonalDataManager.
- ScheduleCommit();
+ return WebDatabase::COMMIT_NEEDED;
}
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
AutofillProfileSyncableService*
diff --git a/chrome/browser/webdata/web_data_service.h b/chrome/browser/webdata/web_data_service.h
index 3dfe4a2..f66d9dc 100644
--- a/chrome/browser/webdata/web_data_service.h
+++ b/chrome/browser/webdata/web_data_service.h
@@ -28,6 +28,7 @@
#include "chrome/browser/search_engines/template_url_id.h"
#include "chrome/browser/webdata/keyword_table.h"
#include "chrome/browser/webdata/web_data_request_manager.h"
+#include "chrome/browser/webdata/web_database.h"
#include "content/public/browser/browser_thread.h"
#include "sql/init_status.h"
@@ -42,7 +43,7 @@ struct IE7PasswordInfo;
class MessageLoop;
class Profile;
class SkBitmap;
-class WebDatabase;
+class WebDatabaseService;
namespace base {
class Thread;
@@ -129,18 +130,23 @@ class WebDataService
// call.
virtual void ShutdownOnUIThread() OVERRIDE;
- // Initializes the web data service. Returns false on failure
- // Takes the path of the profile directory as its argument.
- bool Init(const base::FilePath& profile_path);
-
- // Returns false if Shutdown() has been called.
- bool IsRunning() const;
+ // Initializes the web data service.
+ void Init(const base::FilePath& path);
// Unloads the database without actually shutting down the service. This can
// be used to temporarily reduce the browser process' memory footprint.
void UnloadDatabase();
+ // Unloads the database permanently and shuts down service.
+ void ShutdownDatabase();
+
+ // Returns true if the database load has completetd successfully, and
+ // ShutdownOnUIThread has not yet been called.
virtual bool IsDatabaseLoaded();
+
+ // Returns a pointer to the DB (used by SyncableServices). May return NULL if
+ // the database is not loaded or otherwise unavailable. Must be called on
+ // DBThread.
virtual WebDatabase* GetDatabase();
//////////////////////////////////////////////////////////////////////////////
@@ -320,11 +326,6 @@ class WebDataService
virtual AutocompleteSyncableService*
GetAutocompleteSyncableService() const;
- // Testing
-#ifdef UNIT_TEST
- void set_failed_init(bool value) { failed_init_ = value; }
-#endif
-
protected:
friend class TemplateURLServiceTest;
friend class TemplateURLServiceTestingProfile;
@@ -333,9 +334,6 @@ class WebDataService
virtual ~WebDataService();
- // This is invoked by the unit test; path is the path of the Web Data file.
- bool InitWithPath(const base::FilePath& path);
-
//////////////////////////////////////////////////////////////////////////////
//
// The following methods are only invoked in the web data service thread.
@@ -346,59 +344,31 @@ class WebDataService
content::BrowserThread::UI>;
friend class base::DeleteHelper<WebDataService>;
- // Invoked on the main thread if initializing the db fails.
- void DBInitFailed(sql::InitStatus init_status);
-
- // Initialize the database, if it hasn't already been initialized.
- void InitializeDatabaseIfNecessary();
-
// Initialize any syncable services.
void InitializeSyncableServices();
- // The notification method.
- void NotifyDatabaseLoadedOnUIThread();
-
- // Commit any pending transaction and deletes the database.
- void ShutdownDatabase();
-
// Deletes the syncable services.
void ShutdownSyncableServices();
- // Commit the current transaction and creates a new one.
- void Commit();
-
- // Schedule a task on our worker thread.
- void ScheduleTask(const tracked_objects::Location& from_here,
- const base::Closure& task);
-
- void ScheduleDBTask(const tracked_objects::Location& from_here,
- const base::Closure& task);
-
- WebDataService::Handle ScheduleDBTaskWithResult(
- const tracked_objects::Location& from_here,
- const ResultTask& task,
- WebDataServiceConsumer* consumer);
-
- void DBTaskWrapper(const base::Closure& task,
- scoped_ptr<WebDataRequest> request);
-
- void DBResultTaskWrapper(const ResultTask& task,
- scoped_ptr<WebDataRequest> request);
-
- // Schedule a commit if one is not already pending.
- void ScheduleCommit();
+ void DBInitFailed(sql::InitStatus sql_status);
+ void NotifyDatabaseLoadedOnUIThread();
+ void DatabaseInitOnDB(sql::InitStatus status);
//////////////////////////////////////////////////////////////////////////////
//
// Keywords.
//
//////////////////////////////////////////////////////////////////////////////
- void AddKeywordImpl(const TemplateURLData& data);
- void RemoveKeywordImpl(TemplateURLID id);
- void UpdateKeywordImpl(const TemplateURLData& data);
- scoped_ptr<WDTypedResult> GetKeywordsImpl();
- void SetDefaultSearchProviderImpl(TemplateURLID r);
- void SetBuiltinKeywordVersionImpl(int version);
+ WebDatabase::State AddKeywordImpl(
+ const TemplateURLData& data, WebDatabase* db);
+ WebDatabase::State RemoveKeywordImpl(
+ TemplateURLID id, WebDatabase* db);
+ WebDatabase::State UpdateKeywordImpl(
+ const TemplateURLData& data, WebDatabase* db);
+ scoped_ptr<WDTypedResult> GetKeywordsImpl(WebDatabase* db);
+ WebDatabase::State SetDefaultSearchProviderImpl(
+ TemplateURLID r, WebDatabase* db);
+ WebDatabase::State SetBuiltinKeywordVersionImpl(int version, WebDatabase* db);
//////////////////////////////////////////////////////////////////////////////
//
@@ -406,10 +376,13 @@ class WebDataService
//
//////////////////////////////////////////////////////////////////////////////
- void SetWebAppImageImpl(const GURL& app_url, const SkBitmap& image);
- void SetWebAppHasAllImagesImpl(const GURL& app_url, bool has_all_images);
- void RemoveWebAppImpl(const GURL& app_url);
- scoped_ptr<WDTypedResult> GetWebAppImagesImpl(const GURL& app_url);
+ WebDatabase::State SetWebAppImageImpl(const GURL& app_url,
+ const SkBitmap& image, WebDatabase* db);
+ WebDatabase::State SetWebAppHasAllImagesImpl(const GURL& app_url,
+ bool has_all_images, WebDatabase* db);
+ WebDatabase::State RemoveWebAppImpl(const GURL& app_url, WebDatabase* db);
+ scoped_ptr<WDTypedResult> GetWebAppImagesImpl(
+ const GURL& app_url, WebDatabase* db);
#if defined(ENABLE_WEB_INTENTS)
//////////////////////////////////////////////////////////////////////////////
@@ -417,18 +390,20 @@ class WebDataService
// Web Intents.
//
//////////////////////////////////////////////////////////////////////////////
- void AddWebIntentServiceImpl(
+ WebDatabase::State AddWebIntentServiceImpl(
const webkit_glue::WebIntentServiceData& service);
- void RemoveWebIntentServiceImpl(
+ WebDatabase::State RemoveWebIntentServiceImpl(
const webkit_glue::WebIntentServiceData& service);
scoped_ptr<WDTypedResult> GetWebIntentServicesImpl(const string16& action);
scoped_ptr<WDTypedResult> GetWebIntentServicesForURLImpl(
const string16& service_url);
scoped_ptr<WDTypedResult> GetAllWebIntentServicesImpl();
- void AddDefaultWebIntentServiceImpl(const DefaultWebIntentService& service);
- void RemoveDefaultWebIntentServiceImpl(
+ WebDatabase::State AddDefaultWebIntentServiceImpl(
+ const DefaultWebIntentService& service);
+ WebDatabase::State RemoveDefaultWebIntentServiceImpl(
const DefaultWebIntentService& service);
- void RemoveWebIntentServiceDefaultsImpl(const GURL& service_url);
+ WebDatabase::State RemoveWebIntentServiceDefaultsImpl(
+ const GURL& service_url);
scoped_ptr<WDTypedResult> GetDefaultWebIntentServicesForActionImpl(
const string16& action);
scoped_ptr<WDTypedResult> GetAllDefaultWebIntentServicesImpl();
@@ -440,10 +415,10 @@ class WebDataService
//
//////////////////////////////////////////////////////////////////////////////
- void RemoveAllTokensImpl();
- void SetTokenForServiceImpl(const std::string& service,
- const std::string& token);
- scoped_ptr<WDTypedResult> GetAllTokensImpl();
+ WebDatabase::State RemoveAllTokensImpl(WebDatabase* db);
+ WebDatabase::State SetTokenForServiceImpl(const std::string& service,
+ const std::string& token, WebDatabase* db);
+ scoped_ptr<WDTypedResult> GetAllTokensImpl(WebDatabase* db);
#if defined(OS_WIN)
//////////////////////////////////////////////////////////////////////////////
@@ -451,9 +426,12 @@ class WebDataService
// Password manager.
//
//////////////////////////////////////////////////////////////////////////////
- void AddIE7LoginImpl(const IE7PasswordInfo& info);
- void RemoveIE7LoginImpl(const IE7PasswordInfo& info);
- scoped_ptr<WDTypedResult> GetIE7LoginImpl(const IE7PasswordInfo& info);
+ WebDatabase::State AddIE7LoginImpl(
+ const IE7PasswordInfo& info, WebDatabase* db);
+ WebDatabase::State RemoveIE7LoginImpl(
+ const IE7PasswordInfo& info, WebDatabase* db);
+ scoped_ptr<WDTypedResult> GetIE7LoginImpl(
+ const IE7PasswordInfo& info, WebDatabase* db);
#endif // defined(OS_WIN)
//////////////////////////////////////////////////////////////////////////////
@@ -461,47 +439,44 @@ class WebDataService
// Autofill.
//
//////////////////////////////////////////////////////////////////////////////
- void AddFormElementsImpl(const std::vector<FormFieldData>& fields);
+ WebDatabase::State AddFormElementsImpl(
+ const std::vector<FormFieldData>& fields, WebDatabase* db);
scoped_ptr<WDTypedResult> GetFormValuesForElementNameImpl(
- const string16& name, const string16& prefix, int limit);
- void RemoveFormElementsAddedBetweenImpl(
- const base::Time& delete_begin, const base::Time& delete_end);
- void RemoveExpiredFormElementsImpl();
- void RemoveFormValueForElementNameImpl(const string16& name,
- const string16& value);
- void AddAutofillProfileImpl(const AutofillProfile& profile);
- void UpdateAutofillProfileImpl(const AutofillProfile& profile);
- void RemoveAutofillProfileImpl(const std::string& guid);
- scoped_ptr<WDTypedResult> GetAutofillProfilesImpl();
- void AddCreditCardImpl(const CreditCard& credit_card);
- void UpdateCreditCardImpl(const CreditCard& credit_card);
- void RemoveCreditCardImpl(const std::string& guid);
- scoped_ptr<WDTypedResult> GetCreditCardsImpl();
- void RemoveAutofillProfilesAndCreditCardsModifiedBetweenImpl(
- const base::Time& delete_begin, const base::Time& delete_end);
+ const string16& name, const string16& prefix, int limit, WebDatabase* db);
+ WebDatabase::State RemoveFormElementsAddedBetweenImpl(
+ const base::Time& delete_begin, const base::Time& delete_end,
+ WebDatabase* db);
+ WebDatabase::State RemoveExpiredFormElementsImpl(WebDatabase* db);
+ WebDatabase::State RemoveFormValueForElementNameImpl(
+ const string16& name, const string16& value, WebDatabase* db);
+ WebDatabase::State AddAutofillProfileImpl(
+ const AutofillProfile& profile, WebDatabase* db);
+ WebDatabase::State UpdateAutofillProfileImpl(
+ const AutofillProfile& profile, WebDatabase* db);
+ WebDatabase::State RemoveAutofillProfileImpl(
+ const std::string& guid, WebDatabase* db);
+ scoped_ptr<WDTypedResult> GetAutofillProfilesImpl(WebDatabase* db);
+ WebDatabase::State AddCreditCardImpl(
+ const CreditCard& credit_card, WebDatabase* db);
+ WebDatabase::State UpdateCreditCardImpl(
+ const CreditCard& credit_card, WebDatabase* db);
+ WebDatabase::State RemoveCreditCardImpl(
+ const std::string& guid, WebDatabase* db);
+ scoped_ptr<WDTypedResult> GetCreditCardsImpl(WebDatabase* db);
+ WebDatabase::State RemoveAutofillProfilesAndCreditCardsModifiedBetweenImpl(
+ const base::Time& delete_begin, const base::Time& delete_end,
+ WebDatabase* db);
// Callbacks to ensure that sensitive info is destroyed if request is
// cancelled.
void DestroyAutofillProfileResult(const WDTypedResult* result);
void DestroyAutofillCreditCardResult(const WDTypedResult* result);
- // True once initialization has started.
- bool is_running_;
+ // Our database service.
+ scoped_ptr<WebDatabaseService> wdbs_;
- // The path with which to initialize the database.
- base::FilePath path_;
-
- // Our database. We own the |db_|, but don't use a |scoped_ptr| because the
- // |db_| lifetime must be managed on the database thread.
- WebDatabase* db_;
-
- // Keeps track of all pending requests made to the db.
- scoped_refptr<WebDataRequestManager> request_manager_;
-
- // The application locale. The locale is needed for some database migrations,
- // and must be read on the UI thread. It's cached here so that we can pass it
- // to the migration code on the DB thread.
- const std::string app_locale_;
+ // True if we've received a notification that the WebDatabase has loaded.
+ bool db_loaded_;
// Syncable services for the database data. We own the services, but don't
// use |scoped_ptr|s because the lifetimes must be managed on the database
@@ -511,16 +486,6 @@ class WebDataService
AutocompleteSyncableService* autocomplete_syncable_service_;
AutofillProfileSyncableService* autofill_profile_syncable_service_;
- // Whether the database failed to initialize. We use this to avoid
- // continually trying to reinit.
- bool failed_init_;
-
- // Whether we should commit the database.
- bool should_commit_;
-
- // MessageLoop the WebDataService is created on.
- MessageLoop* main_loop_;
-
DISALLOW_COPY_AND_ASSIGN(WebDataService);
};
diff --git a/chrome/browser/webdata/web_data_service_factory.cc b/chrome/browser/webdata/web_data_service_factory.cc
index a73a76c..4d54619 100644
--- a/chrome/browser/webdata/web_data_service_factory.cc
+++ b/chrome/browser/webdata/web_data_service_factory.cc
@@ -85,8 +85,7 @@ WebDataServiceFactory::BuildServiceInstanceFor(Profile* profile) const {
path = path.Append(chrome::kWebDataFilename);
scoped_refptr<WebDataService> wds(new WebDataService());
- if (!wds->Init(profile->GetPath()))
- NOTREACHED();
+ wds->Init(path);
return wds.get();
}
diff --git a/chrome/browser/webdata/web_data_service_unittest.cc b/chrome/browser/webdata/web_data_service_unittest.cc
index 08b7b7b..c61882f 100644
--- a/chrome/browser/webdata/web_data_service_unittest.cc
+++ b/chrome/browser/webdata/web_data_service_unittest.cc
@@ -77,7 +77,8 @@ class WebDataServiceTest : public testing::Test {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
wds_ = new WebDataService();
- wds_->Init(temp_dir_.path());
+ base::FilePath path = temp_dir_.path().AppendASCII("TestWebDB");
+ wds_->Init(path);
}
virtual void TearDown() {
@@ -85,9 +86,9 @@ class WebDataServiceTest : public testing::Test {
wds_ = NULL;
WaitForDatabaseThread();
- db_thread_.Stop();
MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
MessageLoop::current()->Run();
+ db_thread_.Stop();
}
void WaitForDatabaseThread() {
diff --git a/chrome/browser/webdata/web_data_service_win.cc b/chrome/browser/webdata/web_data_service_win.cc
index 00a34e6..e0e1624 100644
--- a/chrome/browser/webdata/web_data_service_win.cc
+++ b/chrome/browser/webdata/web_data_service_win.cc
@@ -2,46 +2,50 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/webdata/logins_table.h"
#include "chrome/browser/webdata/web_data_service.h"
#include "base/bind.h"
#include "chrome/browser/password_manager/ie7_password.h"
-#include "chrome/browser/webdata/web_database.h"
+#include "chrome/browser/webdata/logins_table.h"
+#include "chrome/browser/webdata/web_database_service.h"
using base::Bind;
void WebDataService::AddIE7Login(const IE7PasswordInfo& info) {
- ScheduleDBTask(FROM_HERE,
- Bind(&WebDataService::AddIE7LoginImpl, this, info));
+ wdbs_->ScheduleDBTask(
+ FROM_HERE, Bind(&WebDataService::AddIE7LoginImpl, this, info));
}
void WebDataService::RemoveIE7Login(const IE7PasswordInfo& info) {
- ScheduleDBTask(FROM_HERE,
- Bind(&WebDataService::RemoveIE7LoginImpl, this, info));
+ wdbs_->ScheduleDBTask(
+ FROM_HERE, Bind(&WebDataService::RemoveIE7LoginImpl, this, info));
}
WebDataService::Handle WebDataService::GetIE7Login(
const IE7PasswordInfo& info,
WebDataServiceConsumer* consumer) {
- return ScheduleDBTaskWithResult(FROM_HERE,
- Bind(&WebDataService::GetIE7LoginImpl, this, info), consumer);
+ return wdbs_->ScheduleDBTaskWithResult(
+ FROM_HERE, Bind(&WebDataService::GetIE7LoginImpl, this, info), consumer);
}
-void WebDataService::AddIE7LoginImpl(const IE7PasswordInfo& info) {
- if (db_->GetLoginsTable()->AddIE7Login(info))
- ScheduleCommit();
+WebDatabase::State WebDataService::AddIE7LoginImpl(
+ const IE7PasswordInfo& info, WebDatabase* db) {
+ if (db->GetLoginsTable()->AddIE7Login(info))
+ return WebDatabase::COMMIT_NEEDED;
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
-void WebDataService::RemoveIE7LoginImpl(const IE7PasswordInfo& info) {
- if (db_->GetLoginsTable()->RemoveIE7Login(info))
- ScheduleCommit();
+WebDatabase::State WebDataService::RemoveIE7LoginImpl(
+ const IE7PasswordInfo& info, WebDatabase* db) {
+ if (db->GetLoginsTable()->RemoveIE7Login(info))
+ return WebDatabase::COMMIT_NEEDED;
+ return WebDatabase::COMMIT_NOT_NEEDED;
}
scoped_ptr<WDTypedResult> WebDataService::GetIE7LoginImpl(
- const IE7PasswordInfo& info) {
+ const IE7PasswordInfo& info, WebDatabase* db) {
IE7PasswordInfo result;
- db_->GetLoginsTable()->GetIE7Login(info, &result);
+ db->GetLoginsTable()->GetIE7Login(info, &result);
return scoped_ptr<WDTypedResult>(
new WDResult<IE7PasswordInfo>(PASSWORD_IE7_RESULT, result));
}
diff --git a/chrome/browser/webdata/web_database.h b/chrome/browser/webdata/web_database.h
index 744741b..6a24985 100644
--- a/chrome/browser/webdata/web_database.h
+++ b/chrome/browser/webdata/web_database.h
@@ -30,6 +30,10 @@ class NotificationService;
// This class manages a SQLite database that stores various web page meta data.
class WebDatabase {
public:
+ enum State {
+ COMMIT_NOT_NEEDED,
+ COMMIT_NEEDED
+ };
// Exposed publicly so the keyword table can access it.
static const int kCurrentVersionNumber;
diff --git a/chrome/browser/webdata/web_database_service.cc b/chrome/browser/webdata/web_database_service.cc
new file mode 100644
index 0000000..543d9ba
--- /dev/null
+++ b/chrome/browser/webdata/web_database_service.cc
@@ -0,0 +1,262 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/webdata/web_database_service.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "chrome/browser/api/webdata/web_data_results.h"
+#include "chrome/browser/api/webdata/web_data_service_consumer.h"
+#include "chrome/browser/webdata/web_data_request_manager.h"
+#include "chrome/browser/webdata/web_data_service.h"
+// TODO(caitkp): Remove this autofill dependency.
+#include "components/autofill/browser/autofill_country.h"
+
+using base::Bind;
+using base::FilePath;
+using content::BrowserThread;
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// WebDataServiceBackend implementation.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Refcounted to allow asynchronous destruction on the DB thread.
+class WebDataServiceBackend
+ : public base::RefCountedThreadSafe<WebDataServiceBackend,
+ BrowserThread::DeleteOnDBThread> {
+ public:
+ explicit WebDataServiceBackend(const FilePath& path);
+
+ // Initializes the database and notifies caller via callback when complete.
+ // Callback is called synchronously.
+ void InitDatabaseWithCallback(
+ const WebDatabaseService::InitCallback& callback);
+
+ // Opens the database file from the profile path if an init has not yet been
+ // attempted. Separated from the constructor to ease construction/destruction
+ // of this object on one thread but database access on the DB thread. Returns
+ // the status of the database.
+ sql::InitStatus LoadDatabaseIfNecessary();
+
+ // Shuts down database. |should_reinit| tells us whether or not it should be
+ // possible to re-initialize the DB after the shutdown.
+ void ShutdownDatabase(bool should_reinit);
+
+ // Task wrappers to run database tasks.
+ void DBWriteTaskWrapper(
+ const WebDatabaseService::WriteTask& task,
+ scoped_ptr<WebDataRequest> request);
+ void DBReadTaskWrapper(
+ const WebDatabaseService::ReadTask& task,
+ scoped_ptr<WebDataRequest> request);
+
+ const scoped_refptr<WebDataRequestManager>& request_manager() {
+ return request_manager_;
+ }
+
+ WebDatabase* database() { return db_.get(); }
+
+ private:
+ friend struct BrowserThread::DeleteOnThread<BrowserThread::DB>;
+ friend class base::DeleteHelper<WebDataServiceBackend>;
+
+ virtual ~WebDataServiceBackend();
+
+ // Commit the current transaction.
+ void Commit();
+
+ // Path to database file.
+ FilePath db_path_;
+
+ scoped_ptr<WebDatabase> db_;
+
+ // Keeps track of all pending requests made to the db.
+ scoped_refptr<WebDataRequestManager> request_manager_;
+
+ // State of database initialization. Used to prevent the executing of tasks
+ // before the db is ready.
+ sql::InitStatus init_status_;
+
+ // True if an attempt has been made to load the database (even if the attempt
+ // fails), used to avoid continually trying to reinit if the db init fails.
+ bool init_complete_;
+
+ // The application locale. The locale is needed for some database migrations,
+ // and must be read on the UI thread. It's cached here so that we can pass it
+ // to the migration code on the DB thread.
+ const std::string app_locale_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebDataServiceBackend);
+};
+
+WebDataServiceBackend::WebDataServiceBackend(const FilePath& path)
+ : db_path_(path),
+ request_manager_(new WebDataRequestManager()),
+ init_status_(sql::INIT_FAILURE),
+ init_complete_(false),
+ app_locale_(AutofillCountry::ApplicationLocale()) {
+}
+
+void WebDataServiceBackend::InitDatabaseWithCallback(
+ const WebDatabaseService::InitCallback& callback) {
+ if (!callback.is_null()) {
+ callback.Run(LoadDatabaseIfNecessary());
+ }
+}
+
+sql::InitStatus WebDataServiceBackend::LoadDatabaseIfNecessary() {
+ if (init_complete_ || db_path_.empty()) {
+ return init_status_;
+ }
+ init_complete_ = true;
+ db_.reset(new WebDatabase());
+ init_status_ = db_->Init(db_path_, app_locale_);
+ if (init_status_ != sql::INIT_OK) {
+ LOG(ERROR) << "Cannot initialize the web database: " << init_status_;
+ db_.reset(NULL);
+ return init_status_;
+ }
+
+ db_->BeginTransaction();
+ return init_status_;
+}
+
+void WebDataServiceBackend::ShutdownDatabase(bool should_reinit) {
+ if (db_ && init_status_ == sql::INIT_OK)
+ db_->CommitTransaction();
+ db_.reset(NULL);
+ init_complete_ = !should_reinit; // Setting init_complete_ to true will ensure
+ // that the init sequence is not re-run.
+
+ init_status_ = sql::INIT_FAILURE;
+}
+
+void WebDataServiceBackend::DBWriteTaskWrapper(
+ const WebDatabaseService::WriteTask& task,
+ scoped_ptr<WebDataRequest> request) {
+ LoadDatabaseIfNecessary();
+ if (db_ && init_status_ == sql::INIT_OK && !request->IsCancelled()) {
+ WebDatabase::State state = task.Run(db_.get());
+ if (state == WebDatabase::COMMIT_NEEDED)
+ Commit();
+ }
+ request_manager_->RequestCompleted(request.Pass());
+}
+
+void WebDataServiceBackend::DBReadTaskWrapper(
+ const WebDatabaseService::ReadTask& task,
+ scoped_ptr<WebDataRequest> request) {
+ LoadDatabaseIfNecessary();
+ if (db_ && init_status_ == sql::INIT_OK && !request->IsCancelled()) {
+ request->SetResult(task.Run(db_.get()).Pass());
+ }
+ request_manager_->RequestCompleted(request.Pass());
+}
+
+WebDataServiceBackend::~WebDataServiceBackend() {
+ ShutdownDatabase(false);
+}
+
+void WebDataServiceBackend::Commit() {
+ if (db_ && init_status_ == sql::INIT_OK) {
+ db_->CommitTransaction();
+ db_->BeginTransaction();
+ } else {
+ NOTREACHED() << "Commit scheduled after Shutdown()";
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+WebDatabaseService::WebDatabaseService(const base::FilePath& path)
+ : path_(path) {
+ // WebDatabaseService should be instantiated on UI thread.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // WebDatabaseService requires DB thread if instantiated.
+ DCHECK(BrowserThread::IsWellKnownThread(BrowserThread::DB));
+}
+
+WebDatabaseService::~WebDatabaseService() {
+}
+
+void WebDatabaseService::LoadDatabase(const InitCallback& callback) {
+ if (!wds_backend_)
+ wds_backend_ = new WebDataServiceBackend(path_);
+
+ BrowserThread::PostTask(
+ BrowserThread::DB,
+ FROM_HERE,
+ Bind(&WebDataServiceBackend::InitDatabaseWithCallback,
+ wds_backend_, callback));
+}
+
+void WebDatabaseService::UnloadDatabase() {
+ if (!wds_backend_)
+ return;
+ BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
+ Bind(&WebDataServiceBackend::ShutdownDatabase,
+ wds_backend_, true));
+}
+
+void WebDatabaseService::ShutdownDatabase() {
+ if (!wds_backend_)
+ return;
+ BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
+ Bind(&WebDataServiceBackend::ShutdownDatabase,
+ wds_backend_, false));
+}
+
+WebDatabase* WebDatabaseService::GetDatabaseOnDB() const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ if (!wds_backend_)
+ return NULL;
+ return wds_backend_->database();
+}
+
+void WebDatabaseService::ScheduleDBTask(
+ const tracked_objects::Location& from_here,
+ const WriteTask& task) {
+ if (!wds_backend_) {
+ NOTREACHED() << "Task scheduled after Shutdown()";
+ return;
+ }
+
+ scoped_ptr<WebDataRequest> request(
+ new WebDataRequest(NULL, wds_backend_->request_manager()));
+
+ BrowserThread::PostTask(BrowserThread::DB, from_here,
+ Bind(&WebDataServiceBackend::DBWriteTaskWrapper, wds_backend_,
+ task, base::Passed(&request)));
+}
+
+WebDataService::Handle WebDatabaseService::ScheduleDBTaskWithResult(
+ const tracked_objects::Location& from_here,
+ const ReadTask& task,
+ WebDataServiceConsumer* consumer) {
+ DCHECK(consumer);
+ WebDataService::Handle handle = 0;
+
+ if (!wds_backend_) {
+ NOTREACHED() << "Task scheduled after Shutdown()";
+ return handle;
+ }
+
+ scoped_ptr<WebDataRequest> request(
+ new WebDataRequest(consumer, wds_backend_->request_manager()));
+ handle = request->GetHandle();
+
+ BrowserThread::PostTask(BrowserThread::DB, from_here,
+ Bind(&WebDataServiceBackend::DBReadTaskWrapper, wds_backend_,
+ task, base::Passed(&request)));
+
+ return handle;
+}
+
+void WebDatabaseService::CancelRequest(WebDataServiceBase::Handle h) {
+ if (!wds_backend_)
+ return;
+ wds_backend_->request_manager()->CancelRequest(h);
+}
diff --git a/chrome/browser/webdata/web_database_service.h b/chrome/browser/webdata/web_database_service.h
new file mode 100644
index 0000000..75a4f4d
--- /dev/null
+++ b/chrome/browser/webdata/web_database_service.h
@@ -0,0 +1,94 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Chromium settings and storage represent user-selected preferences and
+// information and MUST not be extracted, overwritten or modified except
+// through Chromium defined APIs.
+
+#ifndef CHROME_BROWSER_WEBDATA_WEB_DATABASE_SERVICE_H_
+#define CHROME_BROWSER_WEBDATA_WEB_DATABASE_SERVICE_H_
+
+#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "base/compiler_specific.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/api/webdata/web_data_service_base.h"
+#include "chrome/browser/webdata/web_database.h"
+
+class WebDataServiceBackend;
+class WebDataRequestManager;
+
+namespace content {
+class BrowserContext;
+}
+
+namespace tracked_objects {
+class Location;
+}
+
+class WDTypedResult;
+class WebDataServiceConsumer;
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// WebDatabaseService defines the interface to a generic data repository
+// responsible for controlling access to the web database (metadata associated
+// with web pages).
+//
+////////////////////////////////////////////////////////////////////////////////
+
+class WebDatabaseService {
+ public:
+ typedef base::Callback<scoped_ptr<WDTypedResult>(WebDatabase*)> ReadTask;
+ typedef base::Callback<WebDatabase::State(WebDatabase*)> WriteTask;
+ typedef base::Callback<void(sql::InitStatus)> InitCallback;
+
+ // Takes the path to the WebDatabase file.
+ explicit WebDatabaseService(const base::FilePath& path);
+
+ virtual ~WebDatabaseService();
+
+ // Initializes the web database service. Takes a callback which will return
+ // the status of the DB after the init.
+ virtual void LoadDatabase(const InitCallback& callback);
+
+ // Unloads the database without actually shutting down the service. This can
+ // be used to temporarily reduce the browser process' memory footprint.
+ virtual void UnloadDatabase();
+
+ // Unloads database and will not reload.
+ virtual void ShutdownDatabase();
+
+ // Gets a ptr to the WebDatabase (owned by WebDatabaseService).
+ // TODO(caitkp): remove this method once SyncServices no longer depend on it.
+ virtual WebDatabase* GetDatabaseOnDB() const;
+
+ // Schedule an update/write task on the DB thread.
+ virtual void ScheduleDBTask(
+ const tracked_objects::Location& from_here,
+ const WriteTask& task);
+
+ // Schedule a read task on the DB thread.
+ virtual WebDataServiceBase::Handle ScheduleDBTaskWithResult(
+ const tracked_objects::Location& from_here,
+ const ReadTask& task,
+ WebDataServiceConsumer* consumer);
+
+ // Cancel an existing request for a task on the DB thread.
+ // TODO(caitkp): Think about moving the definition of the Handle type to
+ // somewhere else.
+ virtual void CancelRequest(WebDataServiceBase::Handle h);
+
+ private:
+ base::FilePath path_;
+
+ // The primary owner is |WebDatabaseService| but is refcounted because
+ // PostTask on DB thread may outlive us.
+ scoped_refptr<WebDataServiceBackend> wds_backend_;
+};
+
+#endif // CHROME_BROWSER_WEBDATA_WEB_DATABASE_SERVICE_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index bb283fb..68e160f 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2108,6 +2108,8 @@
'browser/webdata/token_service_table.h',
'browser/webdata/web_apps_table.cc',
'browser/webdata/web_apps_table.h',
+ 'browser/webdata/web_database_service.cc',
+ 'browser/webdata/web_database_service.h',
'browser/webdata/web_data_request_manager.cc',
'browser/webdata/web_data_request_manager.h',
'browser/webdata/web_data_service.cc',
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index a10f39a..5142f3e 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -422,9 +422,11 @@ void TestingProfile::CreateBookmarkModel(bool delete_file) {
static scoped_refptr<RefcountedProfileKeyedService> BuildWebDataService(
Profile* profile) {
+ base::FilePath path = profile->GetPath();
+ path = path.Append(chrome::kWebDataFilename);
WebDataService* web_data_service = new WebDataService();
if (web_data_service)
- web_data_service->Init(profile->GetPath());
+ web_data_service->Init(path);
return web_data_service;
}