diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-18 00:19:44 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-18 00:19:44 +0000 |
commit | b3b2d6e76a2cfbb02933298c565d3718b0288774 (patch) | |
tree | 548c4d8fe0b7c7d22c44e045a61c7719977359cc /chrome | |
parent | 5786d3d3a7cd151fb5dc0aa2f1f0d84460fb6cdf (diff) | |
download | chromium_src-b3b2d6e76a2cfbb02933298c565d3718b0288774.zip chromium_src-b3b2d6e76a2cfbb02933298c565d3718b0288774.tar.gz chromium_src-b3b2d6e76a2cfbb02933298c565d3718b0288774.tar.bz2 |
Fixes two related bugs:
. If we can't init the web db a dialog is shown to the user.
. If we can't init the web db the default search provider no longer
becomes NULL.
BUG=28374
TEST=none
Review URL: http://codereview.chromium.org/501090
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@34901 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
18 files changed, 133 insertions, 86 deletions
diff --git a/chrome/browser/history/archived_database.cc b/chrome/browser/history/archived_database.cc index b7cd8bd..1b9e010 100644 --- a/chrome/browser/history/archived_database.cc +++ b/chrome/browser/history/archived_database.cc @@ -64,7 +64,7 @@ bool ArchivedDatabase::Init(const FilePath& file_name) { } CreateMainURLIndex(); - if (EnsureCurrentVersion() != INIT_OK) { + if (EnsureCurrentVersion() != sql::INIT_OK) { db_.Close(); return false; } @@ -86,11 +86,11 @@ sql::Connection& ArchivedDatabase::GetDB() { // Migration ------------------------------------------------------------------- -InitStatus ArchivedDatabase::EnsureCurrentVersion() { +sql::InitStatus ArchivedDatabase::EnsureCurrentVersion() { // We can't read databases newer than we were designed for. if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { LOG(WARNING) << "Archived database is too new."; - return INIT_TOO_NEW; + return sql::INIT_TOO_NEW; } // NOTICE: If you are changing structures for things shared with the archived @@ -103,7 +103,7 @@ InitStatus ArchivedDatabase::EnsureCurrentVersion() { if (cur_version == 1) { if (!DropStarredIDFromURLs()) { LOG(WARNING) << "Unable to update archived database to version 2."; - return INIT_FAILURE; + return sql::INIT_FAILURE; } ++cur_version; meta_table_.SetVersionNumber(cur_version); @@ -118,6 +118,6 @@ InitStatus ArchivedDatabase::EnsureCurrentVersion() { LOG_IF(WARNING, cur_version < kCurrentVersionNumber) << "Archived database version " << cur_version << " is too old to handle."; - return INIT_OK; + return sql::INIT_OK; } } // namespace history diff --git a/chrome/browser/history/archived_database.h b/chrome/browser/history/archived_database.h index 13bc562..c9d8757 100644 --- a/chrome/browser/history/archived_database.h +++ b/chrome/browser/history/archived_database.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_HISTORY_ARCHIVED_DATABASE_H_ #include "app/sql/connection.h" +#include "app/sql/init_status.h" #include "app/sql/meta_table.h" #include "base/basictypes.h" #include "chrome/browser/history/url_database.h" @@ -48,7 +49,7 @@ class ArchivedDatabase : public URLDatabase, // // This assumes it is called from the init function inside a transaction. It // may commit the transaction and start a new one if migration requires it. - InitStatus EnsureCurrentVersion(); + sql::InitStatus EnsureCurrentVersion(); // The database. sql::Connection db_; diff --git a/chrome/browser/history/expire_history_backend_unittest.cc b/chrome/browser/history/expire_history_backend_unittest.cc index 2ccab9b61..03c4eef 100644 --- a/chrome/browser/history/expire_history_backend_unittest.cc +++ b/chrome/browser/history/expire_history_backend_unittest.cc @@ -113,8 +113,7 @@ class ExpireHistoryTest : public testing::Test, FilePath history_name = dir_.Append(kHistoryFile); main_db_.reset(new HistoryDatabase); - if (main_db_->Init(history_name, FilePath()) != - INIT_OK) + if (main_db_->Init(history_name, FilePath()) != sql::INIT_OK) main_db_.reset(); FilePath archived_name = dir_.Append(kArchivedHistoryFile); @@ -124,7 +123,7 @@ class ExpireHistoryTest : public testing::Test, FilePath thumb_name = dir_.Append(kThumbnailFile); thumb_db_.reset(new ThumbnailDatabase); - if (thumb_db_->Init(thumb_name, NULL) != INIT_OK) + if (thumb_db_->Init(thumb_name, NULL) != sql::INIT_OK) thumb_db_.reset(); text_db_.reset(new TextDatabaseManager(dir_, diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc index 9734d4f..4fdcef8 100644 --- a/chrome/browser/history/history_backend.cc +++ b/chrome/browser/history/history_backend.cc @@ -504,15 +504,15 @@ void HistoryBackend::InitImpl() { // History database. db_.reset(new HistoryDatabase()); switch (db_->Init(history_name, tmp_bookmarks_file)) { - case INIT_OK: + case sql::INIT_OK: break; - case INIT_FAILURE: + case sql::INIT_FAILURE: // A NULL db_ will cause all calls on this object to notice this error // and to not continue. delegate_->NotifyProfileError(IDS_COULDNT_OPEN_PROFILE_ERROR); db_.reset(); return; - case INIT_TOO_NEW: + case sql::INIT_TOO_NEW: delegate_->NotifyProfileError(IDS_PROFILE_TOO_NEW_ERROR); db_.reset(); return; @@ -557,7 +557,7 @@ void HistoryBackend::InitImpl() { // Thumbnail database. thumbnail_db_.reset(new ThumbnailDatabase()); if (thumbnail_db_->Init(thumbnail_name, - history_publisher_.get()) != INIT_OK) { + history_publisher_.get()) != sql::INIT_OK) { // Unlike the main database, we don't error out when the database is too // new because this error is much less severe. Generally, this shouldn't // happen since the thumbnail and main datbase versions should be in sync. diff --git a/chrome/browser/history/history_database.cc b/chrome/browser/history/history_database.cc index 37296b0..21a271b 100644 --- a/chrome/browser/history/history_database.cc +++ b/chrome/browser/history/history_database.cc @@ -60,8 +60,8 @@ HistoryDatabase::HistoryDatabase() HistoryDatabase::~HistoryDatabase() { } -InitStatus HistoryDatabase::Init(const FilePath& history_name, - const FilePath& bookmarks_path) { +sql::InitStatus HistoryDatabase::Init(const FilePath& history_name, + const FilePath& bookmarks_path) { // Set the exceptional sqlite error handler. db_.set_error_delegate(GetErrorHandlerForHistoryDb()); @@ -82,13 +82,13 @@ InitStatus HistoryDatabase::Init(const FilePath& history_name, // mode to start out for the in-memory backend to read the data). if (!db_.Open(history_name)) - return INIT_FAILURE; + return sql::INIT_FAILURE; // Wrap the rest of init in a tranaction. This will prevent the database from // getting corrupted if we crash in the middle of initialization or migration. sql::Transaction committer(&db_); if (!committer.Begin()) - return INIT_FAILURE; + return sql::INIT_FAILURE; #if defined(OS_MACOSX) // Exclude the history file and its journal from backups. @@ -106,21 +106,21 @@ InitStatus HistoryDatabase::Init(const FilePath& history_name, // NOTE: If you add something here, also add it to // RecreateAllButStarAndURLTables. if (!meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber)) - return INIT_FAILURE; + return sql::INIT_FAILURE; if (!CreateURLTable(false) || !InitVisitTable() || !InitKeywordSearchTermsTable() || !InitDownloadTable() || !InitSegmentTables()) - return INIT_FAILURE; + return sql::INIT_FAILURE; CreateMainURLIndex(); CreateSupplimentaryURLIndices(); // Version check. - InitStatus version_status = EnsureCurrentVersion(bookmarks_path); - if (version_status != INIT_OK) + sql::InitStatus version_status = EnsureCurrentVersion(bookmarks_path); + if (version_status != sql::INIT_OK) return version_status; ComputeDatabaseMetrics(history_name, db_); - return committer.Commit() ? INIT_OK : INIT_FAILURE; + return committer.Commit() ? sql::INIT_OK : sql::INIT_FAILURE; } void HistoryDatabase::BeginExclusiveMode() { @@ -229,12 +229,12 @@ sql::Connection& HistoryDatabase::GetDB() { // Migration ------------------------------------------------------------------- -InitStatus HistoryDatabase::EnsureCurrentVersion( +sql::InitStatus HistoryDatabase::EnsureCurrentVersion( const FilePath& tmp_bookmarks_path) { // We can't read databases newer than we were designed for. if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { LOG(WARNING) << "History database is too new."; - return INIT_TOO_NEW; + return sql::INIT_TOO_NEW; } // NOTICE: If you are changing structures for things shared with the archived @@ -251,7 +251,7 @@ InitStatus HistoryDatabase::EnsureCurrentVersion( if (!MigrateBookmarksToFile(tmp_bookmarks_path) || !DropStarredIDFromURLs()) { LOG(WARNING) << "Unable to update history database to version 16."; - return INIT_FAILURE; + return sql::INIT_FAILURE; } ++cur_version; meta_table_.SetVersionNumber(cur_version); @@ -278,7 +278,7 @@ InitStatus HistoryDatabase::EnsureCurrentVersion( LOG_IF(WARNING, cur_version < kCurrentVersionNumber) << "History database version " << cur_version << " is too old to handle."; - return INIT_OK; + return sql::INIT_OK; } #if !defined(OS_WIN) diff --git a/chrome/browser/history/history_database.h b/chrome/browser/history/history_database.h index 3bb8520..5bfda56 100644 --- a/chrome/browser/history/history_database.h +++ b/chrome/browser/history/history_database.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_HISTORY_HISTORY_DATABASE_H_ #include "app/sql/connection.h" +#include "app/sql/init_status.h" #include "app/sql/meta_table.h" #include "build/build_config.h" #include "chrome/browser/history/download_database.h" @@ -61,8 +62,8 @@ class HistoryDatabase : public DownloadDatabase, // Must call this function to complete initialization. Will return true on // success. On false, no other function should be called. You may want to call // BeginExclusiveMode after this when you are ready. - InitStatus Init(const FilePath& history_name, - const FilePath& tmp_bookmarks_path); + sql::InitStatus Init(const FilePath& history_name, + const FilePath& tmp_bookmarks_path); // Call to set the mode on the database to exclusive. The default locking mode // is "normal" but we want to run in exclusive mode for slightly better @@ -152,7 +153,7 @@ class HistoryDatabase : public DownloadDatabase, // // This assumes it is called from the init function inside a transaction. It // may commit the transaction and start a new one if migration requires it. - InitStatus EnsureCurrentVersion(const FilePath& tmp_bookmarks_path); + sql::InitStatus EnsureCurrentVersion(const FilePath& tmp_bookmarks_path); #if !defined(OS_WIN) // Converts the time epoch in the database from being 1970-based to being diff --git a/chrome/browser/history/history_types.h b/chrome/browser/history/history_types.h index 89d3851..b35f432 100644 --- a/chrome/browser/history/history_types.h +++ b/chrome/browser/history/history_types.h @@ -37,17 +37,6 @@ typedef int64 DownloadID; // Identifier for a download. typedef int64 FavIconID; // For FavIcons. typedef int64 SegmentID; // URL segments for the most visited view. -// Used as the return value for some databases' init function. -enum InitStatus { - INIT_OK, - - // Some error, usually I/O related opening the file. - INIT_FAILURE, - - // The database is from a future version of the app and can not be read. - INIT_TOO_NEW, -}; - // URLRow --------------------------------------------------------------------- typedef int64 URLID; diff --git a/chrome/browser/history/thumbnail_database.cc b/chrome/browser/history/thumbnail_database.cc index 60b8985..4e6f372 100644 --- a/chrome/browser/history/thumbnail_database.cc +++ b/chrome/browser/history/thumbnail_database.cc @@ -32,8 +32,9 @@ ThumbnailDatabase::~ThumbnailDatabase() { // The DBCloseScoper will delete the DB and the cache. } -InitStatus ThumbnailDatabase::Init(const FilePath& db_name, - const HistoryPublisher* history_publisher) { +sql::InitStatus ThumbnailDatabase::Init( + const FilePath& db_name, + const HistoryPublisher* history_publisher) { history_publisher_ = history_publisher; // Set the exceptional sqlite error handler. @@ -60,7 +61,7 @@ InitStatus ThumbnailDatabase::Init(const FilePath& db_name, db_.set_exclusive_locking(); if (!db_.Open(db_name)) - return INIT_FAILURE; + return sql::INIT_FAILURE; // Scope initialization in a transaction so we can't be partially initialized. sql::Transaction transaction(&db_); @@ -81,7 +82,7 @@ InitStatus ThumbnailDatabase::Init(const FilePath& db_name, !InitThumbnailTable() || !InitFavIconsTable(false)) { db_.Close(); - return INIT_FAILURE; + return sql::INIT_FAILURE; } InitFavIconsIndex(); @@ -89,7 +90,7 @@ InitStatus ThumbnailDatabase::Init(const FilePath& db_name, // in the wild, so we try to continue in that case. if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { LOG(WARNING) << "Thumbnail database is too new."; - return INIT_TOO_NEW; + return sql::INIT_TOO_NEW; } int cur_version = meta_table_.GetVersionNumber(); @@ -97,7 +98,7 @@ InitStatus ThumbnailDatabase::Init(const FilePath& db_name, if (!UpgradeToVersion3()) { LOG(WARNING) << "Unable to update to thumbnail database to version 3."; db_.Close(); - return INIT_FAILURE; + return sql::INIT_FAILURE; } ++cur_version; } @@ -108,10 +109,10 @@ InitStatus ThumbnailDatabase::Init(const FilePath& db_name, // Initialization is complete. if (!transaction.Commit()) { db_.Close(); - return INIT_FAILURE; + return sql::INIT_FAILURE; } - return INIT_OK; + return sql::INIT_OK; } bool ThumbnailDatabase::InitThumbnailTable() { diff --git a/chrome/browser/history/thumbnail_database.h b/chrome/browser/history/thumbnail_database.h index 7fd9202..362edec 100644 --- a/chrome/browser/history/thumbnail_database.h +++ b/chrome/browser/history/thumbnail_database.h @@ -8,6 +8,7 @@ #include <vector> #include "app/sql/connection.h" +#include "app/sql/init_status.h" #include "app/sql/meta_table.h" #include "chrome/browser/history/history_types.h" #include "chrome/browser/history/url_database.h" // For DBCloseScoper. @@ -40,8 +41,8 @@ class ThumbnailDatabase { // Must be called after creation but before any other methods are called. // When not INIT_OK, no other functions should be called. - InitStatus Init(const FilePath& db_name, - const HistoryPublisher* history_publisher); + sql::InitStatus Init(const FilePath& db_name, + const HistoryPublisher* history_publisher); // Transactions on the database. void BeginTransaction(); diff --git a/chrome/browser/history/thumbnail_database_unittest.cc b/chrome/browser/history/thumbnail_database_unittest.cc index 83d67cf..2b63e43 100644 --- a/chrome/browser/history/thumbnail_database_unittest.cc +++ b/chrome/browser/history/thumbnail_database_unittest.cc @@ -69,7 +69,7 @@ class ThumbnailDatabaseTest : public testing::Test { TEST_F(ThumbnailDatabaseTest, AddDelete) { ThumbnailDatabase db; - ASSERT_TRUE(db.Init(file_name_, NULL) == INIT_OK); + ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL)); // Add one page & verify it got added. ThumbnailScore boring(kBoringness, true, true); @@ -112,7 +112,7 @@ TEST_F(ThumbnailDatabaseTest, AddDelete) { TEST_F(ThumbnailDatabaseTest, UseLessBoringThumbnails) { ThumbnailDatabase db; Time now = Time::Now(); - ASSERT_TRUE(db.Init(file_name_, NULL) == INIT_OK); + ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL)); // Add one page & verify it got added. ThumbnailScore boring(kBoringness, true, true); @@ -146,7 +146,7 @@ TEST_F(ThumbnailDatabaseTest, UseLessBoringThumbnails) { TEST_F(ThumbnailDatabaseTest, UseAtTopThumbnails) { ThumbnailDatabase db; Time now = Time::Now(); - ASSERT_TRUE(db.Init(file_name_, NULL) == INIT_OK); + ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL)); // Add one page & verify it got added. Note that it doesn't have // |good_clipping| and isn't |at_top|. @@ -222,7 +222,7 @@ TEST_F(ThumbnailDatabaseTest, ThumbnailTimeDegradation) { const double kBaseBoringness = 0.305; const double kWorseBoringness = 0.345; - ASSERT_TRUE(db.Init(file_name_, NULL) == INIT_OK); + ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL)); // add one page & verify it got added. ThumbnailScore base_boringness(kBaseBoringness, true, true, kFiveHoursAgo); @@ -261,7 +261,7 @@ TEST_F(ThumbnailDatabaseTest, NeverAcceptTotallyBoringThumbnail) { // thumbnail is totally boring. ThumbnailDatabase db; Time now = Time::Now(); - ASSERT_TRUE(db.Init(file_name_, NULL) == INIT_OK); + ASSERT_EQ(sql::INIT_OK, db.Init(file_name_, NULL)); std::vector<unsigned char> jpeg_data; ThumbnailScore score_out; diff --git a/chrome/browser/search_engines/template_url_model.cc b/chrome/browser/search_engines/template_url_model.cc index cbad64a..a356ad0 100644 --- a/chrome/browser/search_engines/template_url_model.cc +++ b/chrome/browser/search_engines/template_url_model.cc @@ -59,6 +59,7 @@ class TemplateURLModel::LessWithPrefix { TemplateURLModel::TemplateURLModel(Profile* profile) : profile_(profile), loaded_(false), + load_failed_(false), load_handle_(0), default_search_provider_(NULL), next_id_(1) { @@ -70,6 +71,7 @@ TemplateURLModel::TemplateURLModel(const Initializer* initializers, const int count) : profile_(NULL), loaded_(true), + load_failed_(false), load_handle_(0), service_(NULL), default_search_provider_(NULL), @@ -521,7 +523,7 @@ void TemplateURLModel::SetDefaultSearchProvider(const TemplateURL* url) { } const TemplateURL* TemplateURLModel::GetDefaultSearchProvider() { - if (loaded_) + if (loaded_ && !load_failed_) return default_search_provider_; if (!prefs_default_search_provider_.get()) { @@ -576,8 +578,10 @@ void TemplateURLModel::OnWebDataServiceRequestDone( load_handle_ = 0; if (!result) { - // Results are null if the database went away. + // Results are null if the database went away or (most likely) wasn't + // loaded. loaded_ = true; + load_failed_ = true; NotifyLoaded(); return; } diff --git a/chrome/browser/search_engines/template_url_model.h b/chrome/browser/search_engines/template_url_model.h index 044ec23..5b76234 100644 --- a/chrome/browser/search_engines/template_url_model.h +++ b/chrome/browser/search_engines/template_url_model.h @@ -320,6 +320,9 @@ class TemplateURLModel : public WebDataServiceConsumer, // Whether the keywords have been loaded. bool loaded_; + // Did loading fail? This is only valid if loaded_ is true. + bool load_failed_; + // If non-zero, we're waiting on a load. WebDataService::Handle load_handle_; @@ -340,8 +343,8 @@ class TemplateURLModel : public WebDataServiceConsumer, const TemplateURL* default_search_provider_; // The default search provider from preferences. This is only valid if - // GetDefaultSearchProvider is invoked and we haven't been loaded. Once loaded - // this is not used. + // GetDefaultSearchProvider is invoked and we haven't been loaded or loading + // failed. If loading was successful this is not used. scoped_ptr<TemplateURL> prefs_default_search_provider_; // ID assigned to next TemplateURL added to this model. This is an ever diff --git a/chrome/browser/search_engines/template_url_model_unittest.cc b/chrome/browser/search_engines/template_url_model_unittest.cc index 1edad67..1c50fc1 100644 --- a/chrome/browser/search_engines/template_url_model_unittest.cc +++ b/chrome/browser/search_engines/template_url_model_unittest.cc @@ -31,7 +31,7 @@ class QuitTask2 : public Task { // Subclass the TestingProfile so that it can return a WebDataService. class TemplateURLModelTestingProfile : public TestingProfile { public: - TemplateURLModelTestingProfile() : TestingProfile() { } + TemplateURLModelTestingProfile() : TestingProfile() {} void SetUp() { // Name a subdirectory of the temp directory. @@ -87,7 +87,7 @@ class TestingTemplateURLModel : public TemplateURLModel { private: std::wstring search_term_; - DISALLOW_EVIL_CONSTRUCTORS(TestingTemplateURLModel); + DISALLOW_COPY_AND_ASSIGN(TestingTemplateURLModel); }; class TemplateURLModelTest : public testing::Test, @@ -739,3 +739,21 @@ TEST_F(TemplateURLModelTest, MergeDeletesUnusedProviders) { // Don't remove |t_url3|; we'd need to make it non-default first, and why // bother when the model shutdown will clean it up for us. } + +// Simulates failing to load the webdb and makes sure the default search +// provider is valid. +TEST_F(TemplateURLModelTest, FailedInit) { + VerifyLoad(); + + model_.reset(NULL); + + profile_->GetWebDataService(Profile::EXPLICIT_ACCESS)->UnloadDatabase(); + profile_->GetWebDataService(Profile::EXPLICIT_ACCESS)->set_failed_init(true); + + ResetModel(false); + model_->Load(); + BlockTillServiceProcessesRequests(); + + ASSERT_TRUE(model_->GetDefaultSearchProvider()); +} + diff --git a/chrome/browser/webdata/web_data_service.cc b/chrome/browser/webdata/web_data_service.cc index 1b81ac2..5ca9c31 100644 --- a/chrome/browser/webdata/web_data_service.cc +++ b/chrome/browser/webdata/web_data_service.cc @@ -14,6 +14,8 @@ #include "chrome/common/notification_details.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" #include "webkit/glue/password_form.h" //////////////////////////////////////////////////////////////////////////////// @@ -26,11 +28,13 @@ using base::Time; using webkit_glue::FormField; using webkit_glue::PasswordForm; -WebDataService::WebDataService() : thread_(NULL), - db_(NULL), - failed_init_(false), - should_commit_(false), - next_request_handle_(1) { +WebDataService::WebDataService() + : thread_(NULL), + db_(NULL), + failed_init_(false), + should_commit_(false), + next_request_handle_(1), + main_loop_(MessageLoop::current()) { } WebDataService::~WebDataService() { @@ -407,6 +411,14 @@ WebDataService::Handle WebDataService::GetBlacklistLogins( return request->GetHandle(); } +void WebDataService::DBInitFailed(sql::InitStatus init_status) { + Source<WebDataService> source(this); + int message_id = (init_status == sql::INIT_FAILURE) ? + IDS_COULDNT_OPEN_PROFILE_ERROR : IDS_PROFILE_TOO_NEW_ERROR; + NotificationService::current()->Notify(NotificationType::PROFILE_ERROR, + source, Details<int>(&message_id)); +} + //////////////////////////////////////////////////////////////////////////////// // // The following methods are executed in Chrome_WebDataThread. @@ -433,10 +445,15 @@ void WebDataService::InitializeDatabaseIfNecessary() { // 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(); - if (!db->Init(path_)) { + sql::InitStatus init_status = db->Init(path_); + if (init_status != sql::INIT_OK) { NOTREACHED() << "Cannot initialize the web database"; failed_init_ = true; delete db; + if (main_loop_) { + main_loop_->PostTask(FROM_HERE, + NewRunnableMethod(this, &WebDataService::DBInitFailed, init_status)); + } return; } diff --git a/chrome/browser/webdata/web_data_service.h b/chrome/browser/webdata/web_data_service.h index b87803c..3a6c83b 100644 --- a/chrome/browser/webdata/web_data_service.h +++ b/chrome/browser/webdata/web_data_service.h @@ -8,6 +8,7 @@ #include <map> #include <vector> +#include "app/sql/init_status.h" #include "base/file_path.h" #include "base/lock.h" #include "base/ref_counted.h" @@ -401,6 +402,11 @@ class WebDataService : public base::RefCountedThreadSafe<WebDataService> { void RemoveFormValueForElementName(const string16& name, const string16& value); + // Testing +#ifdef UNIT_TEST + void set_failed_init(bool value) { failed_init_ = value; } +#endif + protected: friend class TemplateURLModelTest; friend class TemplateURLModelTestingProfile; @@ -430,6 +436,9 @@ class WebDataService : public base::RefCountedThreadSafe<WebDataService> { ~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(); @@ -534,6 +543,9 @@ class WebDataService : public base::RefCountedThreadSafe<WebDataService> { typedef std::map<Handle, WebDataRequest*> RequestMap; RequestMap pending_requests_; + // MessageLoop the WebDataService is created on. + MessageLoop* main_loop_; + DISALLOW_EVIL_CONSTRUCTORS(WebDataService); }; diff --git a/chrome/browser/webdata/web_database.cc b/chrome/browser/webdata/web_database.cc index 41d5e8b..edeb0d6 100644 --- a/chrome/browser/webdata/web_database.cc +++ b/chrome/browser/webdata/web_database.cc @@ -136,7 +136,7 @@ void WebDatabase::CommitTransaction() { db_.CommitTransaction(); } -bool WebDatabase::Init(const FilePath& db_name) { +sql::InitStatus WebDatabase::Init(const FilePath& db_name) { // Set the exceptional sqlite error handler. db_.set_error_delegate(GetErrorHandlerForWebDb()); @@ -154,19 +154,19 @@ bool WebDatabase::Init(const FilePath& db_name) { db_.set_exclusive_locking(); if (!db_.Open(db_name)) - return false; + return sql::INIT_FAILURE; // Initialize various tables sql::Transaction transaction(&db_); if (!transaction.Begin()) - return false; + return sql::INIT_FAILURE; // Version check. if (!meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber)) - return false; + return sql::INIT_FAILURE; if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { LOG(WARNING) << "Web database is too new."; - return false; + return sql::INIT_TOO_NEW; } // Initialize the tables. @@ -174,13 +174,13 @@ bool WebDatabase::Init(const FilePath& db_name) { !InitWebAppsTable() || !InitAutofillTable() || !InitAutofillDatesTable()) { LOG(WARNING) << "Unable to initialize the web database."; - return false; + return sql::INIT_FAILURE; } // If the file on disk is an older database version, bring it up to date. MigrateOldVersionsAsNeeded(); - return transaction.Commit(); + return transaction.Commit() ? sql::INIT_OK : sql::INIT_FAILURE; } bool WebDatabase::SetWebAppImage(const GURL& url, const SkBitmap& image) { diff --git a/chrome/browser/webdata/web_database.h b/chrome/browser/webdata/web_database.h index f5451ab..24bba2d 100644 --- a/chrome/browser/webdata/web_database.h +++ b/chrome/browser/webdata/web_database.h @@ -8,6 +8,7 @@ #include <vector> #include "app/sql/connection.h" +#include "app/sql/init_status.h" #include "app/sql/meta_table.h" #include "chrome/browser/search_engines/template_url.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -40,8 +41,8 @@ class WebDatabase { ~WebDatabase(); // Initialize the database given a name. The name defines where the sqlite - // file is. If false is returned, no other method should be called. - bool Init(const FilePath& db_name); + // file is. If this returns an error code, no other method should be called. + sql::InitStatus Init(const FilePath& db_name); // Transactions management void BeginTransaction(); diff --git a/chrome/browser/webdata/web_database_unittest.cc b/chrome/browser/webdata/web_database_unittest.cc index eb94e4f..ef62933 100644 --- a/chrome/browser/webdata/web_database_unittest.cc +++ b/chrome/browser/webdata/web_database_unittest.cc @@ -113,7 +113,7 @@ class WebDatabaseTest : public testing::Test { TEST_F(WebDatabaseTest, Keywords) { WebDatabase db; - ASSERT_TRUE(db.Init(file_)); + ASSERT_EQ(sql::INIT_OK, db.Init(file_)); TemplateURL template_url; template_url.set_short_name(L"short_name"); @@ -174,7 +174,7 @@ TEST_F(WebDatabaseTest, Keywords) { TEST_F(WebDatabaseTest, KeywordMisc) { WebDatabase db; - ASSERT_TRUE(db.Init(file_)); + ASSERT_EQ(sql::INIT_OK, db.Init(file_)); ASSERT_EQ(0, db.GetDefaulSearchProviderID()); ASSERT_EQ(0, db.GetBuitinKeywordVersion()); @@ -189,7 +189,7 @@ TEST_F(WebDatabaseTest, KeywordMisc) { TEST_F(WebDatabaseTest, UpdateKeyword) { WebDatabase db; - ASSERT_TRUE(db.Init(file_)); + ASSERT_EQ(sql::INIT_OK, db.Init(file_)); TemplateURL template_url; template_url.set_short_name(L"short_name"); @@ -251,7 +251,7 @@ TEST_F(WebDatabaseTest, UpdateKeyword) { TEST_F(WebDatabaseTest, KeywordWithNoFavicon) { WebDatabase db; - ASSERT_TRUE(db.Init(file_)); + ASSERT_EQ(sql::INIT_OK, db.Init(file_)); TemplateURL template_url; template_url.set_short_name(L"short_name"); @@ -278,7 +278,7 @@ TEST_F(WebDatabaseTest, KeywordWithNoFavicon) { TEST_F(WebDatabaseTest, Logins) { WebDatabase db; - ASSERT_TRUE(db.Init(file_)); + ASSERT_EQ(sql::INIT_OK, db.Init(file_)); std::vector<PasswordForm*> result; @@ -411,7 +411,7 @@ TEST_F(WebDatabaseTest, Logins) { TEST_F(WebDatabaseTest, Autofill) { WebDatabase db; - ASSERT_TRUE(db.Init(file_)); + ASSERT_EQ(sql::INIT_OK, db.Init(file_)); Time t1 = Time::Now(); @@ -645,7 +645,7 @@ static void ClearResults(std::vector<PasswordForm*>* results) { TEST_F(WebDatabaseTest, ClearPrivateData_SavedPasswords) { WebDatabase db; - ASSERT_TRUE(db.Init(file_)); + ASSERT_EQ(sql::INIT_OK, db.Init(file_)); std::vector<PasswordForm*> result; @@ -687,7 +687,7 @@ TEST_F(WebDatabaseTest, ClearPrivateData_SavedPasswords) { TEST_F(WebDatabaseTest, BlacklistedLogins) { WebDatabase db; - ASSERT_TRUE(db.Init(file_)); + ASSERT_EQ(sql::INIT_OK, db.Init(file_)); std::vector<PasswordForm*> result; // Verify the database is empty. @@ -726,7 +726,7 @@ TEST_F(WebDatabaseTest, BlacklistedLogins) { TEST_F(WebDatabaseTest, WebAppHasAllImages) { WebDatabase db; - ASSERT_TRUE(db.Init(file_)); + ASSERT_EQ(sql::INIT_OK, db.Init(file_)); GURL url("http://google.com/"); // Initial value for unknown web app should be false. @@ -744,7 +744,7 @@ TEST_F(WebDatabaseTest, WebAppHasAllImages) { TEST_F(WebDatabaseTest, WebAppImages) { WebDatabase db; - ASSERT_TRUE(db.Init(file_)); + ASSERT_EQ(sql::INIT_OK, db.Init(file_)); GURL url("http://google.com/"); // Web app should initially have no images. |