1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/diagnostics/sqlite_diagnostics.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "app/sql/connection.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/sql/diagnostic_error_delegate.h" 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "app/sql/statement.h" 1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/file_util.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/memory/singleton.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/metrics/histogram.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/path_service.h" 15731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/string_number_conversions.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "chrome/common/chrome_constants.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/chrome_paths.h" 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "third_party/sqlite/sqlite3.h" 2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "webkit/appcache/appcache_interfaces.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/database/database_tracker.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Generic diagnostic test class for checking sqlite db integrity. 264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochclass SqliteIntegrityTest : public DiagnosticTest { 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public: 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SqliteIntegrityTest(bool critical, const string16& title, 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const FilePath& profile_relative_db_path) 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : DiagnosticTest(title), 31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen critical_(critical), 32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen db_path_(profile_relative_db_path) { 33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual int GetId() { return 0; } 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual bool ExecuteImpl(DiagnosticsModel::Observer* observer) { 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath path = GetUserDefaultProfileDir(); 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path = path.Append(db_path_); 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!file_util::PathExists(path)) { 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordOutcome(ASCIIToUTF16("File not found"), 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch critical_ ? DiagnosticsModel::TEST_FAIL_CONTINUE : 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DiagnosticsModel::TEST_OK); 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int errors = 0; 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { // This block scopes the lifetime of the db objects. 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sql::Connection db; 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db.set_exclusive_locking(); 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db.Open(path)) { 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordFailure(ASCIIToUTF16("Cannot open DB. Possibly corrupted")); 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sql::Statement s(db.GetUniqueStatement("PRAGMA integrity_check;")); 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!s) { 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int error = db.GetErrorCode(); 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (SQLITE_BUSY == error) { 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordFailure(ASCIIToUTF16("DB locked by another process")); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string16 str(ASCIIToUTF16("Pragma failed. Error: ")); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch str += base::IntToString16(error); 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordFailure(str); 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (s.Step()) { 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string result(s.ColumnString(0)); 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ("ok" != result) 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++errors; 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // All done. Report to the user. 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (errors != 0) { 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string16 str(ASCIIToUTF16("Database corruption detected :")); 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch str += base::IntToString16(errors) + ASCIIToUTF16(" errors"); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordFailure(str); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordSuccess(ASCIIToUTF16("no corruption detected")); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool critical_; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath db_path_; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(SqliteIntegrityTest); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Uniquifier to use the sql::DiagnosticErrorDelegate template which 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// requires a static name() method. 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate <size_t unique> 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass HistogramUniquifier { 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const char* name() { 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* kHistogramNames[] = { 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sqlite.Cookie.Error", 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sqlite.History.Error", 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sqlite.Thumbnail.Error", 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sqlite.Text.Error", 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sqlite.Web.Error" 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kHistogramNames[unique]; 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsql::ErrorDelegate* GetErrorHandlerForCookieDb() { 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new sql::DiagnosticErrorDelegate<HistogramUniquifier<0> >(); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsql::ErrorDelegate* GetErrorHandlerForHistoryDb() { 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new sql::DiagnosticErrorDelegate<HistogramUniquifier<1> >(); 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsql::ErrorDelegate* GetErrorHandlerForThumbnailDb() { 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new sql::DiagnosticErrorDelegate<HistogramUniquifier<2> >(); 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsql::ErrorDelegate* GetErrorHandlerForTextDb() { 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new sql::DiagnosticErrorDelegate<HistogramUniquifier<3> >(); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsql::ErrorDelegate* GetErrorHandlerForWebDb() { 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new sql::DiagnosticErrorDelegate<HistogramUniquifier<4> >(); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDiagnosticTest* MakeSqliteWebDbTest() { 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new SqliteIntegrityTest(true, ASCIIToUTF16("Web DB"), 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath(chrome::kWebDataFilename)); 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDiagnosticTest* MakeSqliteCookiesDbTest() { 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new SqliteIntegrityTest(true, ASCIIToUTF16("Cookies DB"), 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath(chrome::kCookieFilename)); 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDiagnosticTest* MakeSqliteHistoryDbTest() { 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new SqliteIntegrityTest(true, ASCIIToUTF16("History DB"), 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath(chrome::kHistoryFilename)); 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDiagnosticTest* MakeSqliteArchivedHistoryDbTest() { 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new SqliteIntegrityTest(false, ASCIIToUTF16("Archived History DB"), 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath(chrome::kArchivedHistoryFilename)); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDiagnosticTest* MakeSqliteThumbnailsDbTest() { 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new SqliteIntegrityTest(false, ASCIIToUTF16("Thumbnails DB"), 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath(chrome::kThumbnailsFilename)); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDiagnosticTest* MakeSqliteAppCacheDbTest() { 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath appcache_dir(chrome::kAppCacheDirname); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath appcache_db = appcache_dir.Append(appcache::kAppCacheDatabaseName); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new SqliteIntegrityTest(false, ASCIIToUTF16("AppCache DB"), 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch appcache_db); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDiagnosticTest* MakeSqliteWebDatabaseTrackerDbTest() { 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath databases_dir(webkit_database::kDatabaseDirectoryName); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath tracker_db = 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch databases_dir.Append(webkit_database::kTrackerDatabaseFileName); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new SqliteIntegrityTest(false, ASCIIToUTF16("DatabaseTracker DB"), 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracker_db); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch