| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_SAFE_BROWSING_DB_V4_DATABASE_H_ |
| #define COMPONENTS_SAFE_BROWSING_DB_V4_DATABASE_H_ |
| |
| #include "base/callback.h" |
| #include "base/files/file_path.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/sequenced_task_runner.h" |
| #include "base/single_thread_task_runner.h" |
| #include "components/safe_browsing_db/v4_protocol_manager_util.h" |
| #include "components/safe_browsing_db/v4_store.h" |
| |
| namespace safe_browsing { |
| |
| class V4Database; |
| |
| // Scheduled when the database has been read from disk and is ready to process |
| // resource reputation requests. |
| typedef base::Callback<void(std::unique_ptr<V4Database>)> |
| NewDatabaseReadyCallback; |
| |
| // Scheduled when the checksum for all the stores in the database has been |
| // verified to match the expected value. Stores for which the checksum did not |
| // match are passed as the argument and need to be reset. |
| typedef base::Callback<void(const std::vector<ListIdentifier>&)> |
| DatabaseReadyForUpdatesCallback; |
| |
| // This callback is scheduled once the database has finished processing the |
| // update requests for all stores and is ready to process the next set of update |
| // requests. |
| typedef base::Callback<void()> DatabaseUpdatedCallback; |
| |
| // Maps the ListIdentifiers to their corresponding in-memory stores, which |
| // contain the hash prefixes for that ListIdentifier as well as manage their |
| // storage on disk. |
| typedef base::hash_map<ListIdentifier, std::unique_ptr<V4Store>> StoreMap; |
| |
| // Associates metadata for a list with its ListIdentifier. |
| struct ListInfo { |
| ListInfo(const bool fetch_updates, |
| const std::string& filename, |
| const ListIdentifier& list_id, |
| const SBThreatType sb_threat_type); |
| ~ListInfo(); |
| |
| ListIdentifier list_id() const { return list_id_; } |
| std::string filename() const { return filename_; } |
| SBThreatType sb_threat_type() const { return sb_threat_type_; } |
| bool fetch_updates() const { return fetch_updates_; } |
| |
| private: |
| // Whether to fetch and store updates for this list. |
| bool fetch_updates_; |
| |
| // The ASCII name of the file on disk. This file is created inside the |
| // user-data directory. For instance, the ListIdentifier could be for URL |
| // expressions for UwS on Windows platform, and the corresponding file on disk |
| // could be named: "UrlUws.store" |
| std::string filename_; |
| |
| // The list being read from/written to the disk. |
| ListIdentifier list_id_; |
| |
| // The threat type enum value for this store. |
| SBThreatType sb_threat_type_; |
| |
| ListInfo(); |
| }; |
| |
| typedef std::vector<ListInfo> ListInfos; |
| |
| // Factory for creating V4Database. Tests implement this factory to create fake |
| // databases for testing. |
| class V4DatabaseFactory { |
| public: |
| virtual ~V4DatabaseFactory() {} |
| virtual V4Database* CreateV4Database( |
| const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
| const base::FilePath& base_dir_path, |
| const ListInfos& list_infos) = 0; |
| }; |
| |
| // The on-disk databases are shared among all profiles, as it doesn't contain |
| // user-specific data. This object is not thread-safe, i.e. all its methods |
| // should be used on the same thread that it was created on, unless specified |
| // otherwise. |
| // The hash-prefixes of each type are managed by a V4Store (including saving to |
| // and reading from disk). |
| // The V4Database serves as a single place to manage all the V4Stores. |
| class V4Database { |
| public: |
| // Factory method to create a V4Database. It creates the database on the |
| // provided |db_task_runner| containing stores in |store_file_name_map|. When |
| // the database creation is complete, it runs the NewDatabaseReadyCallback on |
| // the same thread as it was called. |
| static void Create( |
| const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
| const base::FilePath& base_path, |
| const ListInfos& list_infos, |
| NewDatabaseReadyCallback callback); |
| |
| // Destroys the provided v4_database on its task_runner since this may be a |
| // long operation. |
| static void Destroy(std::unique_ptr<V4Database> v4_database); |
| |
| virtual ~V4Database(); |
| |
| // Updates the stores with the response received from the SafeBrowsing service |
| // and calls the db_updated_callback when done. |
| void ApplyUpdate(std::unique_ptr<ParsedServerResponse> parsed_server_response, |
| DatabaseUpdatedCallback db_updated_callback); |
| |
| // Returns the current state of each of the stores being managed. |
| std::unique_ptr<StoreStateMap> GetStoreStateMap(); |
| |
| // Check if all the selected stores are available and populated. |
| // Returns false if any of |stores_to_check| don't have valid data. |
| // A store may be unavailble if either it hasn't yet gotten a proper |
| // full-update (just after install, or corrupted/missing file), or if it's |
| // not supported in this build (i.e. Chromium). |
| virtual bool AreStoresAvailable(const StoresToCheck& stores_to_check) const; |
| |
| // Searches for a hash prefix matching the |full_hash| in stores in the |
| // database, filtered by |stores_to_check|, and returns the identifier of the |
| // store along with the matching hash prefix in |matched_hash_prefix_map|. |
| virtual void GetStoresMatchingFullHash( |
| const FullHash& full_hash, |
| const StoresToCheck& stores_to_check, |
| StoreAndHashPrefixes* matched_store_and_full_hashes); |
| |
| // Resets the stores in |stores_to_reset| to an empty state. This is done if |
| // the checksum doesn't match the expected value. |
| void ResetStores(const std::vector<ListIdentifier>& stores_to_reset); |
| |
| // Schedules verification of the checksum of each store read from disk on task |
| // runner. If the checksum doesn't match, that store is passed to the |
| // |db_ready_for_updates_callback|. At the end, |
| // |db_ready_for_updates_callback| is scheduled (on the same thread as it was |
| // called) to indicate that the database updates can now be scheduled. |
| void VerifyChecksum( |
| DatabaseReadyForUpdatesCallback db_ready_for_updates_callback); |
| |
| // Records the size of each of the stores managed by this database, along |
| // with the combined size of all the stores. |
| void RecordFileSizeHistograms(); |
| |
| protected: |
| V4Database(const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
| std::unique_ptr<StoreMap> store_map); |
| |
| private: |
| friend class V4DatabaseTest; |
| FRIEND_TEST_ALL_PREFIXES(V4DatabaseTest, TestSetupDatabaseWithFakeStores); |
| FRIEND_TEST_ALL_PREFIXES(V4DatabaseTest, |
| TestSetupDatabaseWithFakeStoresFailsReset); |
| FRIEND_TEST_ALL_PREFIXES(V4DatabaseTest, TestApplyUpdateWithNewStates); |
| FRIEND_TEST_ALL_PREFIXES(V4DatabaseTest, TestApplyUpdateWithNoNewState); |
| FRIEND_TEST_ALL_PREFIXES(V4DatabaseTest, TestApplyUpdateWithEmptyUpdate); |
| FRIEND_TEST_ALL_PREFIXES(V4DatabaseTest, TestApplyUpdateWithInvalidUpdate); |
| FRIEND_TEST_ALL_PREFIXES(V4DatabaseTest, TestSomeStoresMatchFullHash); |
| |
| // Makes the passed |factory| the factory used to instantiate a V4Store. Only |
| // for tests. |
| static void RegisterStoreFactoryForTest(V4StoreFactory* factory) { |
| factory_ = factory; |
| } |
| |
| // Factory method to create a V4Database. When the database creation is |
| // complete, it calls the NewDatabaseReadyCallback on |callback_task_runner|. |
| static void CreateOnTaskRunner( |
| const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
| const base::FilePath& base_path, |
| const ListInfos& list_infos, |
| const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, |
| NewDatabaseReadyCallback callback, |
| const base::TimeTicks create_start_time); |
| |
| // Callback called when a new store has been created and is ready to be used. |
| // This method updates the store_map_ to point to the new store, which causes |
| // the old store to get deleted. |
| void UpdatedStoreReady(ListIdentifier identifier, |
| std::unique_ptr<V4Store> store); |
| |
| // See |VerifyChecksum|. |
| void VerifyChecksumOnTaskRunner( |
| const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, |
| DatabaseReadyForUpdatesCallback db_ready_for_updates_callback); |
| |
| const scoped_refptr<base::SequencedTaskRunner> db_task_runner_; |
| |
| // Map of ListIdentifier to the V4Store. |
| const std::unique_ptr<StoreMap> store_map_; |
| |
| DatabaseUpdatedCallback db_updated_callback_; |
| |
| // The factory that controls the creation of V4Store objects. |
| static V4StoreFactory* factory_; |
| |
| // The number of stores for which the update request is pending. When this |
| // goes down to 0, that indicates that the database has updated all the stores |
| // that needed updating and is ready for the next update. It should only be |
| // accessed on the IO thread. |
| int pending_store_updates_; |
| |
| DISALLOW_COPY_AND_ASSIGN(V4Database); |
| }; |
| |
| } // namespace safe_browsing |
| |
| #endif // COMPONENTS_SAFE_BROWSING_DB_V4_DATABASE_H_ |