| Index: components/subresource_filter/core/browser/ruleset_service.h
|
| diff --git a/components/subresource_filter/core/browser/ruleset_service.h b/components/subresource_filter/core/browser/ruleset_service.h
|
| index 33ddbfab713e197c44dc3ec4f3ee60e6d30f9b9d..4c2fc08a156fe4aff3973ab90ac1bb5a29677ef1 100644
|
| --- a/components/subresource_filter/core/browser/ruleset_service.h
|
| +++ b/components/subresource_filter/core/browser/ruleset_service.h
|
| @@ -11,6 +11,7 @@
|
| #include <string>
|
| #include <vector>
|
|
|
| +#include "base/callback_forward.h"
|
| #include "base/files/file.h"
|
| #include "base/files/file_path.h"
|
| #include "base/macros.h"
|
| @@ -30,13 +31,22 @@ namespace subresource_filter {
|
|
|
| class RulesetDistributor;
|
|
|
| -// Encapsulates the combination of the binary format version of the ruleset, and
|
| -// the version of the ruleset's contents.
|
| -struct RulesetVersion {
|
| - RulesetVersion();
|
| - RulesetVersion(const std::string& content_version, int format_version);
|
| - ~RulesetVersion();
|
| - RulesetVersion& operator=(const RulesetVersion&);
|
| +// Encapsulates the combination of the binary format version of the indexed
|
| +// ruleset, and the version of the ruleset contents.
|
| +//
|
| +// The wire format of unindexed rules coming through the component updater
|
| +// is expected to be relatively stable, so a ruleset is uniquely identified by
|
| +// its content version.
|
| +//
|
| +// In contrast, the binary format of the index data structures is expected to
|
| +// evolve over time, so the indexed ruleset is identified by a pair of versions:
|
| +// the content version of the rules that have been indexed; and the binary
|
| +// format version of the indexed data structures.
|
| +struct IndexedRulesetVersion {
|
| + IndexedRulesetVersion();
|
| + IndexedRulesetVersion(const std::string& content_version, int format_version);
|
| + ~IndexedRulesetVersion();
|
| + IndexedRulesetVersion& operator=(const IndexedRulesetVersion&);
|
|
|
| static void RegisterPrefs(PrefRegistrySimple* registry);
|
|
|
| @@ -47,45 +57,48 @@ struct RulesetVersion {
|
|
|
| void SaveToPrefs(PrefService* local_state) const;
|
| void ReadFromPrefs(PrefService* local_state);
|
| - std::string AsString() const;
|
| + base::FilePath GetSubdirectoryPathForVersion(
|
| + const base::FilePath& base_dir) const;
|
|
|
| std::string content_version;
|
| int format_version = 0;
|
| };
|
|
|
| -// Responsible for versioned storage of subresource filtering rules, and for
|
| -// supplying the most up-to-date version to the registered RulesetDistributors
|
| -// for distribution.
|
| +// Responsible for indexing subresource filtering rules that are downloaded
|
| +// through the component updater; for versioned storage of the indexed ruleset;
|
| +// and for supplying the most up-to-date version of the indexed ruleset to the
|
| +// RulesetDistributors for distribution.
|
| //
|
| -// Files corresponding to each version of the ruleset are stored in a separate
|
| -// subdirectory inside |ruleset_base_dir| named after the version. The version
|
| -// information of the most recent successfully stored ruleset is written into
|
| -// |local_state|. The invariant is maintained that the version pointed to by
|
| -// preferences will exist on disk at any point in time. All file operations are
|
| -// posted to |blocking_task_runner|.
|
| +// Files corresponding to each version of the indexed ruleset are stored in a
|
| +// separate subdirectory inside |indexed_ruleset_base_dir| named after the
|
| +// version. The version information of the most recent successfully stored
|
| +// ruleset is written into |local_state|. The invariant is maintained that the
|
| +// version pointed to by preferences, if valid, will exist on disk at any point
|
| +// in time. All file operations are posted to |blocking_task_runner|.
|
| class RulesetService : public base::SupportsWeakPtr<RulesetService> {
|
| public:
|
| + // Creates a new instance that will immediately publish the most recently
|
| + // indexed version of the ruleset if one is available according to prefs.
|
| + // See class comments for details of arguments.
|
| RulesetService(PrefService* local_state,
|
| scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
|
| - const base::FilePath& base_dir);
|
| + const base::FilePath& indexed_ruleset_base_dir);
|
| virtual ~RulesetService();
|
|
|
| - // Notifies that new data has arrived from the component updater.
|
| - virtual void NotifyRulesetVersionAvailable(const std::string& rules,
|
| - const base::Version& version);
|
| -
|
| - // Persists a new |content_version| of the |ruleset_data|, then, on success,
|
| - // publishes it through the registered distributors. The |ruleset_data| must
|
| - // be a function of the |content_version| in the mathematical sense, i.e.
|
| - // different |ruleset_data| contents should have different |content_versions|.
|
| + // Indexes, stores, and publishes the specified |content_version| of the
|
| + // subresource filtering rules available at |unindexed_ruleset_path|, unless
|
| + // the specified version matches that of the most recently indexed version, in
|
| + // which case it does nothing. The |unindexed_ruleset_path| needs to remain
|
| + // accessible even after the method returns.
|
| + //
|
| + // Computation-heavy steps and I/O are performed on a background thread.
|
| + // Still, to prevent start-up congestion, this method should be called at the
|
| + // earliest shortly after start-up.
|
| //
|
| - // Trying to store a ruleset with the same version for a second time will
|
| - // silenty fail on Windows if the previously stored copy of the rules is
|
| - // still in use. This, however, means that the new rules must have been
|
| - // successfully stored on the first try, otherwise they would not have been
|
| - // published. Therefore, the operation would have been idempotent anyway.
|
| - void StoreAndPublishUpdatedRuleset(std::vector<uint8_t> ruleset_data,
|
| - const std::string& content_version);
|
| + // Virtual so that it can be mocked out in tests.
|
| + virtual void IndexAndStoreAndPublishRulesetVersionIfNeeded(
|
| + const base::FilePath& unindexed_ruleset_path,
|
| + const std::string& content_version);
|
|
|
| // Registers a |distributor| that will be notified each time a new version of
|
| // the ruleset becomes avalable. The |distributor| will be destroyed along
|
| @@ -95,26 +108,47 @@ class RulesetService : public base::SupportsWeakPtr<RulesetService> {
|
| private:
|
| friend class SubresourceFilteringRulesetServiceTest;
|
|
|
| - // Writes a new |version| of the ruleset |data| into the correspondingly named
|
| - // subdirectory under |base_dir|, and returns true on success.
|
| + using WriteRulesetCallback =
|
| + base::Callback<void(const IndexedRulesetVersion&)>;
|
| +
|
| + // Posts a task to the |blocking_task_runner_| to index and persist a new
|
| + // |content_version| of the unindexed |ruleset|. Then, on success, updates the
|
| + // most recently indexed version in preferences and invokes |success_callback|
|
| + // on the calling thread. There is no callback on failure.
|
| + void IndexAndStoreRuleset(const base::FilePath& unindexed_ruleset_path,
|
| + const std::string& content_version,
|
| + const WriteRulesetCallback& success_callback);
|
| +
|
| + // Reads the unindexed rules from |unindexed_ruleset_path|, indexes them, and
|
| + // calls WriteRuleset() to write the indexed ruleset data. To be called on the
|
| + // |blocking_task_runner_|.
|
| + static bool IndexAndWriteRuleset(
|
| + const base::FilePath& indexed_ruleset_base_dir,
|
| + const IndexedRulesetVersion& indexed_version,
|
| + const base::FilePath& unindexed_ruleset_path);
|
| +
|
| + // Writes the indexed ruleset |data| of the given |length| to the subdirectory
|
| + // corresponding to |indexed_version| under |indexed_ruleset_base_dir|.
|
| + // Returns true on success. To be called on the |blocking_task_runner_|.
|
| //
|
| - // It will attempt to overwrite the previously stored ruleset with the same
|
| - // version, if any. Doing so is needed in case the earlier write was
|
| - // interrupted, but will silently fail on Windows in case the earlier write
|
| - // was successful and the ruleset is in use. See the comment above regarding
|
| - // why this is not an issue in practice.
|
| - static bool WriteRuleset(const base::FilePath& base_dir,
|
| - const RulesetVersion& version,
|
| - std::vector<uint8_t> data);
|
| -
|
| - void OnWrittenRuleset(const RulesetVersion& version, bool success);
|
| - void OpenAndPublishRuleset(const RulesetVersion& version);
|
| + // Writing is factored out into this separate function so it can be
|
| + // independently exercised in tests.
|
| + static bool WriteRuleset(const base::FilePath& indexed_ruleset_base_dir,
|
| + const IndexedRulesetVersion& indexed_version,
|
| + const uint8_t* data,
|
| + size_t length);
|
| +
|
| + void OnWrittenRuleset(const IndexedRulesetVersion& version,
|
| + const WriteRulesetCallback& result_callback,
|
| + bool success);
|
| +
|
| + void OpenAndPublishRuleset(const IndexedRulesetVersion& version);
|
| void OnOpenedRuleset(base::File::Error error);
|
|
|
| PrefService* const local_state_;
|
| scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
|
|
|
| - const base::FilePath base_dir_;
|
| + const base::FilePath indexed_ruleset_base_dir_;
|
| std::unique_ptr<base::FileProxy> ruleset_data_;
|
| std::vector<std::unique_ptr<RulesetDistributor>> distributors_;
|
|
|
|
|