Reinitialize the cookie database if the meta table gets corrupted.

This has been shown to occur in the wild. At the moment users in this situation will simply get a failure to load or persist cookies (though cookies will work within the current session). After this change, users will see their Cookie database wiped out and reinitialized, but loading and persisting should work going forward.

A histogram tracks how often this scenario is detected - it should probably spike as this is rolled out to new channels and then taper off (hopefully approaching 0).

This is a minimal version with the hopes of being eligible for patching into M18. The preferred long-term version is here: http://codereview.chromium.org/9567022/

TBR=shess
BUG=111376
TEST=unit_tests --gtest_filter=SQLitePersistentCookieStoreTest.TestInvalidMetaTableRecovery

Review URL: http://codereview.chromium.org/9602001

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@124899 0039d316-1c4b-4281-b951-d872f2087c98
parent 62727eb1
...@@ -768,10 +768,22 @@ bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() { ...@@ -768,10 +768,22 @@ bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() {
// Put future migration cases here. // Put future migration cases here.
// When the version is too old, we just try to continue anyway, there should if (cur_version < kCurrentVersionNumber) {
// not be a released product that makes a database too old for us to handle. UMA_HISTOGRAM_COUNTS_100("Cookie.CorruptMetaTable", 1);
LOG_IF(WARNING, cur_version < kCurrentVersionNumber) <<
"Cookie database version " << cur_version << " is too old to handle."; meta_table_.Reset();
db_.reset(new sql::Connection);
if (!file_util::Delete(path_, false) ||
!db_->Open(path_) ||
!meta_table_.Init(
db_.get(), kCurrentVersionNumber, kCompatibleVersionNumber)) {
UMA_HISTOGRAM_COUNTS_100("Cookie.CorruptMetaTableRecoveryFailed", 1);
NOTREACHED() << "Unable to reset the cookie DB.";
meta_table_.Reset();
db_.reset();
return false;
}
}
return true; return true;
} }
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_constants.h"
#include "content/test/test_browser_thread.h" #include "content/test/test_browser_thread.h"
#include "googleurl/src/gurl.h" #include "googleurl/src/gurl.h"
#include "sql/connection.h"
#include "sql/meta_table.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
using content::BrowserThread; using content::BrowserThread;
...@@ -137,6 +139,49 @@ TEST_F(SQLitePersistentCookieStoreTest, RemoveOnDestruction) { ...@@ -137,6 +139,49 @@ TEST_F(SQLitePersistentCookieStoreTest, RemoveOnDestruction) {
temp_dir_.path().Append(chrome::kCookieFilename))); temp_dir_.path().Append(chrome::kCookieFilename)));
} }
TEST_F(SQLitePersistentCookieStoreTest, TestInvalidMetaTableRecovery) {
InitializeStore(false);
AddCookie("A", "B", "http://foo.bar", "/", base::Time::Now());
DestroyStore();
// Load up the store and verify that it has good data in it.
std::vector<net::CookieMonster::CanonicalCookie*> cookies;
CreateAndLoad(false, &cookies);
ASSERT_EQ(1U, cookies.size());
ASSERT_STREQ("http://foo.bar", cookies[0]->Domain().c_str());
ASSERT_STREQ("A", cookies[0]->Name().c_str());
ASSERT_STREQ("B", cookies[0]->Value().c_str());
DestroyStore();
STLDeleteContainerPointers(cookies.begin(), cookies.end());
cookies.clear();
// Now corrupt the meta table.
{
sql::Connection db;
ASSERT_TRUE(db.Open(temp_dir_.path().Append(chrome::kCookieFilename)));
sql::MetaTable meta_table_;
meta_table_.Init(&db, 0, 0);
meta_table_.SetVersionNumber(0);
meta_table_.SetCompatibleVersionNumber(0);
db.Close();
}
// Upon loading, the database should be reset to a good, blank state.
CreateAndLoad(false, &cookies);
ASSERT_EQ(0U, cookies.size());
// Verify that, after, recovery, the database persists properly.
AddCookie("X", "Y", "http://foo.bar", "/", base::Time::Now());
DestroyStore();
CreateAndLoad(false, &cookies);
ASSERT_EQ(1U, cookies.size());
ASSERT_STREQ("http://foo.bar", cookies[0]->Domain().c_str());
ASSERT_STREQ("X", cookies[0]->Name().c_str());
ASSERT_STREQ("Y", cookies[0]->Value().c_str());
STLDeleteContainerPointers(cookies.begin(), cookies.end());
cookies.clear();
}
// Test if data is stored as expected in the SQLite database. // Test if data is stored as expected in the SQLite database.
TEST_F(SQLitePersistentCookieStoreTest, TestPersistance) { TEST_F(SQLitePersistentCookieStoreTest, TestPersistance) {
InitializeStore(false); InitializeStore(false);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment