blob: fc8781e67c340b103af348033a0214e311e29c25 [file] [log] [blame]
// Copyright 2017 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_SUBRESOURCE_FILTER_CONTENT_BROWSER_VERIFIED_RULESET_DEALER_H_
#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_VERIFIED_RULESET_DEALER_H_
#include <memory>
#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "components/subresource_filter/content/common/ruleset_dealer.h"
namespace base {
class File;
} // namespace base
namespace subresource_filter {
class MemoryMappedRuleset;
// The integrity verification status of a given ruleset version.
//
// A ruleset file starts from the kNotVerified state, after which it can be
// classified as kIntact, kCorrupt, or kInvalidFile upon integrity verification.
//
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class RulesetVerificationStatus {
kNotVerified = 0,
kIntact = 1,
kCorrupt = 2,
kInvalidFile = 3,
kMaxValue = kInvalidFile,
};
// This class is the same as RulesetDealer, but additionally does a one-time
// integrity checking on the ruleset before handing it out from GetRuleset().
//
// The |status| of verification is persisted throughout the entire lifetime of
// |this| object, and is reset to kNotVerified only when a new ruleset is
// supplied to SetRulesetFile() method.
class VerifiedRulesetDealer : public RulesetDealer {
public:
class Handle;
VerifiedRulesetDealer();
~VerifiedRulesetDealer() override;
// RulesetDealer:
void SetRulesetFile(base::File ruleset_file) override;
scoped_refptr<const MemoryMappedRuleset> GetRuleset() override;
// Opens file and use it as ruleset file on success. Returns valid
// |base::File| in the case of file opened and set. Returns invalid
// |base::File| in the case of file open error. In the case of error
// ruleset dealer continues to use the previous file (if any).
base::File OpenAndSetRulesetFile(int expected_checksum,
const base::FilePath& file_path);
// For tests only.
RulesetVerificationStatus status() const { return status_; }
private:
RulesetVerificationStatus status_ = RulesetVerificationStatus::kNotVerified;
// Associated with the current |ruleset_file_|;
int expected_checksum_ = 0;
DISALLOW_COPY_AND_ASSIGN(VerifiedRulesetDealer);
};
// The UI-thread handle that owns a VerifiedRulesetDealer living on a dedicated
// sequenced |task_runner|. Provides asynchronous access to the instance, and
// destroys it asynchronously.
class VerifiedRulesetDealer::Handle {
public:
// Creates a VerifiedRulesetDealer that is owned by this handle, accessed
// through this handle, but lives on |task_runner|.
explicit Handle(scoped_refptr<base::SequencedTaskRunner> task_runner);
~Handle();
// Returns the |task_runner| on which the VerifiedRulesetDealer, as well as
// the MemoryMappedRulesets it creates, should be accessed.
base::SequencedTaskRunner* task_runner() { return task_runner_; }
// Invokes |callback| on |task_runner|, providing a pointer to the underlying
// VerifiedRulesetDealer as an argument. The pointer is guaranteed to be valid
// at least until the callback returns.
void GetDealerAsync(
base::OnceCallback<void(VerifiedRulesetDealer*)> callback);
// Schedules file open to use as a new ruleset file. In the case of success,
// the new and valid |base::File| is passed to |callback|. In the case of
// error an invalid |base::File| is passed to |callback| and dealer continues
// to use previous ruleset file (if any).
void TryOpenAndSetRulesetFile(const base::FilePath& path,
int expected_checksum,
base::OnceCallback<void(base::File)> callback);
private:
// Note: Raw pointer, |dealer_| already holds a reference to |task_runner_|.
base::SequencedTaskRunner* task_runner_;
std::unique_ptr<VerifiedRulesetDealer, base::OnTaskRunnerDeleter> dealer_;
base::SequenceChecker sequence_checker_;
DISALLOW_COPY_AND_ASSIGN(Handle);
};
// Holds a strong reference to MemoryMappedRuleset, and provides acceess to it.
//
// Initially holds an empty reference, allowing this object to be created on the
// UI-thread synchronously, hence letting the Handle to be created synchronously
// and be immediately used by clients on the UI-thread, while the
// MemoryMappedRuleset is retrieved on the |task_runner| in a deferred manner.
class VerifiedRuleset {
public:
class Handle;
VerifiedRuleset();
~VerifiedRuleset();
// Can return nullptr even after initialization in case no ruleset is
// available, or if the ruleset is corrupted.
const MemoryMappedRuleset* Get() const {
DCHECK(sequence_checker_.CalledOnValidSequence());
return ruleset_.get();
}
private:
// Initializes |ruleset_| with the one provided by the ruleset |dealer|.
void Initialize(VerifiedRulesetDealer* dealer);
scoped_refptr<const MemoryMappedRuleset> ruleset_;
base::SequenceChecker sequence_checker_;
DISALLOW_COPY_AND_ASSIGN(VerifiedRuleset);
};
// The UI-thread handle that owns a VerifiedRuleset living on a dedicated
// sequenced |task_runner|, same as the VerifiedRulesetDealer lives on. Provides
// asynchronous access to the instance, and destroys it asynchronously.
class VerifiedRuleset::Handle {
public:
// Creates a VerifiedRuleset and initializes it asynchronously on a
// |task_runner| using |dealer_handle|. The instance remains owned by this
// handle, but living and accessed on the |task_runner|.
explicit Handle(VerifiedRulesetDealer::Handle* dealer_handle);
~Handle();
// Returns the |task_runner| on which the VerifiedRuleset, as well as the
// MemoryMappedRuleset it holds a reference to, should be accessed.
base::SequencedTaskRunner* task_runner() { return task_runner_; }
// Invokes |callback| on |task_runner|, providing a pointer to the underlying
// VerifiedRuleset as an argument. The pointer is guaranteed to be valid at
// least until the callback returns.
void GetRulesetAsync(base::OnceCallback<void(VerifiedRuleset*)> callback);
private:
// This is to allow ADSF to post |ruleset_.get()| pointer to |task_runner_|.
friend class AsyncDocumentSubresourceFilter;
// Note: Raw pointer, |ruleset_| already holds a reference to |task_runner_|.
base::SequencedTaskRunner* task_runner_;
std::unique_ptr<VerifiedRuleset, base::OnTaskRunnerDeleter> ruleset_;
base::SequenceChecker sequence_checker_;
DISALLOW_COPY_AND_ASSIGN(Handle);
};
} // namespace subresource_filter
#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_VERIFIED_RULESET_DEALER_H_