15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/sandbox_origin_database.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <utility> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 175e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 185e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h" 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/fileapi/file_system_util.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/db.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::CharType kOriginDatabaseName[] = 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FILE_PATH_LITERAL("Origins"); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kOriginKeyPrefix[] = "ORIGIN:"; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kLastPathKey[] = "LAST_PATH"; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int64 kMinimumReportIntervalHours = 1; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInitStatusHistogramLabel[] = "FileSystem.OriginDatabaseInit"; 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kDatabaseRepairHistogramLabel[] = "FileSystem.OriginDatabaseRepair"; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum InitStatus { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_STATUS_OK = 0, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_STATUS_CORRUPTION, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_STATUS_IO_ERROR, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_STATUS_UNKNOWN_ERROR, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_STATUS_MAX 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)enum RepairResult { 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_REPAIR_SUCCEEDED = 0, 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_REPAIR_FAILED, 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_REPAIR_MAX 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string OriginToOriginKey(const std::string& origin) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string key(kOriginKeyPrefix); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return key + origin; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* LastPathKey() { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kLastPathKey; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace storage { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)SandboxOriginDatabase::SandboxOriginDatabase( 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& file_system_directory, 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) leveldb::Env* env_override) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : file_system_directory_(file_system_directory), 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) env_override_(env_override) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)SandboxOriginDatabase::~SandboxOriginDatabase() { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool SandboxOriginDatabase::Init(InitOption init_option, 71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecoveryOption recovery_option) { 72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FilePath db_path = GetDatabasePath(); 767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (init_option == FAIL_IF_NONEXISTENT && !base::PathExists(db_path)) 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string path = FilePathToString(db_path); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leveldb::Options options; 817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch options.max_open_files = 0; // Use minimum. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.create_if_missing = true; 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (env_override_) 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) options.env = env_override_; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leveldb::DB* db; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leveldb::Status status = leveldb::DB::Open(options, path, &db); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportInitStatus(status); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.ok()) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(db); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleError(FROM_HERE, status); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Corruption due to missing necessary MANIFEST-* file causes IOError instead 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // of Corruption error. 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Try to repair database even when IOError case. 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!status.IsCorruption() && !status.IsIOError()) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (recovery_option) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FAIL_ON_CORRUPTION: 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case REPAIR_ON_CORRUPTION: 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LOG(WARNING) << "Attempting to repair SandboxOriginDatabase."; 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RepairDatabase(path)) { 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION(kDatabaseRepairHistogramLabel, 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_REPAIR_SUCCEEDED, DB_REPAIR_MAX); 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LOG(WARNING) << "Repairing SandboxOriginDatabase completed."; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION(kDatabaseRepairHistogramLabel, 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_REPAIR_FAILED, DB_REPAIR_MAX); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fall through 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DELETE_ON_CORRUPTION: 1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::DeleteFile(file_system_directory_, true)) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateDirectory(file_system_directory_)) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Init(init_option, FAIL_ON_CORRUPTION); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool SandboxOriginDatabase::RepairDatabase(const std::string& db_path) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!db_.get()); 1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch leveldb::Options options; 1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch options.max_open_files = 0; // Use minimum. 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (env_override_) 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) options.env = env_override_; 1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!leveldb::RepairDB(db_path, options).ok() || 133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) !Init(FAIL_IF_NONEXISTENT, FAIL_ON_CORRUPTION)) { 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LOG(WARNING) << "Failed to repair SandboxOriginDatabase."; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if the repaired entries match with what we have on disk. 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<base::FilePath> directories; 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator file_enum(file_system_directory_, 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) false /* recursive */, 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator::DIRECTORIES); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path_each; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!(path_each = file_enum.Next()).empty()) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directories.insert(path_each.BaseName()); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<base::FilePath>::iterator db_dir_itr = 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) directories.find(base::FilePath(kOriginDatabaseName)); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we have the database file in its directory and therefore we are 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // working on the correct path. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(db_dir_itr != directories.end()); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directories.erase(db_dir_itr); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<OriginRecord> origins; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ListAllOrigins(&origins)) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DropDatabase(); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete any obsolete entries from the origins database. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<OriginRecord>::iterator db_origin_itr = origins.begin(); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_origin_itr != origins.end(); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++db_origin_itr) { 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<base::FilePath>::iterator dir_itr = 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directories.find(db_origin_itr->path); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dir_itr == directories.end()) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RemovePathForOrigin(db_origin_itr->origin)) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DropDatabase(); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directories.erase(dir_itr); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete any directories not listed in the origins database. 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::set<base::FilePath>::iterator dir_itr = directories.begin(); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dir_itr != directories.end(); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++dir_itr) { 1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::DeleteFile(file_system_directory_.Append(*dir_itr), 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true /* recursive */)) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DropDatabase(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SandboxOriginDatabase::HandleError( 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& from_here, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const leveldb::Status& status) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(); 19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LOG(ERROR) << "SandboxOriginDatabase failed at: " 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << from_here.ToString() << " with error: " << status.ToString(); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SandboxOriginDatabase::ReportInitStatus(const leveldb::Status& status) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time now = base::Time::Now(); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta minimum_interval = 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromHours(kMinimumReportIntervalHours); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (last_reported_time_ + minimum_interval >= now) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_reported_time_ = now; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.ok()) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_STATUS_OK, INIT_STATUS_MAX); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (status.IsCorruption()) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_STATUS_CORRUPTION, INIT_STATUS_MAX); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (status.IsIOError()) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_STATUS_IO_ERROR, INIT_STATUS_MAX); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INIT_STATUS_UNKNOWN_ERROR, INIT_STATUS_MAX); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool SandboxOriginDatabase::HasOriginPath(const std::string& origin) { 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!Init(FAIL_IF_NONEXISTENT, REPAIR_ON_CORRUPTION)) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (origin.empty()) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string path; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leveldb::Status status = 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->Get(leveldb::ReadOptions(), OriginToOriginKey(origin), &path); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.ok()) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsNotFound()) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleError(FROM_HERE, status); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool SandboxOriginDatabase::GetPathForOrigin( 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& origin, base::FilePath* directory) { 238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!Init(CREATE_IF_NONEXISTENT, REPAIR_ON_CORRUPTION)) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(directory); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (origin.empty()) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string path_string; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string origin_key = OriginToOriginKey(origin); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leveldb::Status status = 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->Get(leveldb::ReadOptions(), origin_key, &path_string); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.IsNotFound()) { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int last_path_number; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetLastPathNumber(&last_path_number)) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path_string = base::StringPrintf("%03u", last_path_number + 1); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // store both back as a single transaction 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leveldb::WriteBatch batch; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) batch.Put(LastPathKey(), path_string); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) batch.Put(origin_key, path_string); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = db_->Write(leveldb::WriteOptions(), &batch); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!status.ok()) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleError(FROM_HERE, status); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.ok()) { 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *directory = StringToFilePath(path_string); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleError(FROM_HERE, status); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool SandboxOriginDatabase::RemovePathForOrigin(const std::string& origin) { 271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!Init(CREATE_IF_NONEXISTENT, REPAIR_ON_CORRUPTION)) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leveldb::Status status = 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->Delete(leveldb::WriteOptions(), OriginToOriginKey(origin)); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.ok() || status.IsNotFound()) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleError(FROM_HERE, status); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool SandboxOriginDatabase::ListAllOrigins( 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<OriginRecord>* origins) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(origins); 284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!Init(CREATE_IF_NONEXISTENT, REPAIR_ON_CORRUPTION)) { 285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) origins->clear(); 286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string origin_key_prefix = OriginToOriginKey(std::string()); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->Seek(origin_key_prefix); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) origins->clear(); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (iter->Valid() && 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartsWithASCII(iter->key().ToString(), origin_key_prefix, true)) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string origin = 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->key().ToString().substr(origin_key_prefix.length()); 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = StringToFilePath(iter->value().ToString()); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) origins->push_back(OriginRecord(origin, path)); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->Next(); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SandboxOriginDatabase::DropDatabase() { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)base::FilePath SandboxOriginDatabase::GetDatabasePath() const { 308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return file_system_directory_.Append(kOriginDatabaseName); 309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void SandboxOriginDatabase::RemoveDatabase() { 312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DropDatabase(); 3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(GetDatabasePath(), true /* recursive */); 314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool SandboxOriginDatabase::GetLastPathNumber(int* number) { 317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(db_); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(number); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string number_string; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leveldb::Status status = 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->Get(leveldb::ReadOptions(), LastPathKey(), &number_string); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.ok()) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringToInt(number_string, number); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!status.IsNotFound()) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleError(FROM_HERE, status); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that this is a totally new database, and initialize it. 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->SeekToFirst(); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter->Valid()) { // DB was not empty, but had no last path number! 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "File system origin database is corrupt!"; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is always the first write into the database. If we ever add a 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // version number, they should go in in a single transaction. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->Put(leveldb::WriteOptions(), LastPathKey(), std::string("-1")); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!status.ok()) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleError(FROM_HERE, status); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *number = -1; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 34703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} // namespace storage 348