sqlite_diagnostics.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/diagnostics/sqlite_diagnostics.h" 6 7#include "base/file_util.h" 8#include "base/logging.h" 9#include "base/memory/singleton.h" 10#include "base/metrics/histogram.h" 11#include "base/path_service.h" 12#include "base/strings/string_number_conversions.h" 13#include "base/utf_string_conversions.h" 14#include "chrome/common/chrome_constants.h" 15#include "chrome/common/chrome_paths.h" 16#include "components/webdata/common/webdata_constants.h" 17#include "content/public/common/content_constants.h" 18#include "sql/connection.h" 19#include "sql/statement.h" 20#include "third_party/sqlite/sqlite3.h" 21#include "webkit/appcache/appcache_interfaces.h" 22#include "webkit/browser/database/database_tracker.h" 23 24namespace { 25 26// Generic diagnostic test class for checking sqlite db integrity. 27class SqliteIntegrityTest : public DiagnosticTest { 28 public: 29 SqliteIntegrityTest(bool critical, const string16& title, 30 const base::FilePath& profile_relative_db_path) 31 : DiagnosticTest(title), 32 critical_(critical), 33 db_path_(profile_relative_db_path) { 34 } 35 36 virtual int GetId() OVERRIDE { return 0; } 37 38 virtual bool ExecuteImpl(DiagnosticsModel::Observer* observer) OVERRIDE { 39 base::FilePath path = GetUserDefaultProfileDir(); 40 path = path.Append(db_path_); 41 if (!file_util::PathExists(path)) { 42 RecordOutcome(ASCIIToUTF16("File not found"), 43 critical_ ? DiagnosticsModel::TEST_FAIL_CONTINUE : 44 DiagnosticsModel::TEST_OK); 45 return true; 46 } 47 48 int errors = 0; 49 { // This block scopes the lifetime of the db objects. 50 sql::Connection db; 51 db.set_exclusive_locking(); 52 if (!db.Open(path)) { 53 RecordFailure(ASCIIToUTF16("Cannot open DB. Possibly corrupted")); 54 return true; 55 } 56 sql::Statement s(db.GetUniqueStatement("PRAGMA integrity_check;")); 57 if (!s.is_valid()) { 58 int error = db.GetErrorCode(); 59 if (SQLITE_BUSY == error) { 60 RecordFailure(ASCIIToUTF16("DB locked by another process")); 61 } else { 62 string16 str(ASCIIToUTF16("Pragma failed. Error: ")); 63 str += base::IntToString16(error); 64 RecordFailure(str); 65 } 66 return false; 67 } 68 while (s.Step()) { 69 std::string result(s.ColumnString(0)); 70 if ("ok" != result) 71 ++errors; 72 } 73 } 74 // All done. Report to the user. 75 if (errors != 0) { 76 string16 str(ASCIIToUTF16("Database corruption detected :")); 77 str += base::IntToString16(errors) + ASCIIToUTF16(" errors"); 78 RecordFailure(str); 79 return true; 80 } 81 RecordSuccess(ASCIIToUTF16("no corruption detected")); 82 return true; 83 } 84 85 private: 86 bool critical_; 87 base::FilePath db_path_; 88 DISALLOW_COPY_AND_ASSIGN(SqliteIntegrityTest); 89}; 90 91} // namespace 92 93DiagnosticTest* MakeSqliteWebDbTest() { 94 return new SqliteIntegrityTest(true, ASCIIToUTF16("Web DB"), 95 base::FilePath(kWebDataFilename)); 96} 97 98DiagnosticTest* MakeSqliteCookiesDbTest() { 99 return new SqliteIntegrityTest(true, ASCIIToUTF16("Cookies DB"), 100 base::FilePath(chrome::kCookieFilename)); 101} 102 103DiagnosticTest* MakeSqliteHistoryDbTest() { 104 return new SqliteIntegrityTest(true, ASCIIToUTF16("History DB"), 105 base::FilePath(chrome::kHistoryFilename)); 106} 107 108DiagnosticTest* MakeSqliteArchivedHistoryDbTest() { 109 return new SqliteIntegrityTest( 110 false, ASCIIToUTF16("Archived History DB"), 111 base::FilePath(chrome::kArchivedHistoryFilename)); 112} 113 114DiagnosticTest* MakeSqliteThumbnailsDbTest() { 115 return new SqliteIntegrityTest(false, ASCIIToUTF16("Thumbnails DB"), 116 base::FilePath(chrome::kThumbnailsFilename)); 117} 118 119DiagnosticTest* MakeSqliteAppCacheDbTest() { 120 base::FilePath appcache_dir(content::kAppCacheDirname); 121 base::FilePath appcache_db = 122 appcache_dir.Append(appcache::kAppCacheDatabaseName); 123 return new SqliteIntegrityTest(false, ASCIIToUTF16("AppCache DB"), 124 appcache_db); 125} 126 127DiagnosticTest* MakeSqliteWebDatabaseTrackerDbTest() { 128 base::FilePath databases_dir(webkit_database::kDatabaseDirectoryName); 129 base::FilePath tracker_db = 130 databases_dir.Append(webkit_database::kTrackerDatabaseFileName); 131 return new SqliteIntegrityTest(false, ASCIIToUTF16("DatabaseTracker DB"), 132 tracker_db); 133} 134