#ifndef EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_RULESET_MANAGER_H_
#define EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_RULESET_MANAGER_H_
#include <stddef.h>
#include <memory>
#include <optional>
#include <set>
#include <utility>
#include <vector>
#include "base/containers/flat_set.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "extensions/browser/api/declarative_net_request/constants.h"
#include "extensions/browser/api/declarative_net_request/utils.h"
#include "extensions/common/extension_id.h"
#include "extensions/common/permissions/permissions_data.h"
namespace content {
class BrowserContext;
class NavigationHandle;
class RenderFrameHost;
}
namespace net {
class HttpResponseHeaders;
}
namespace extensions {
class ExtensionPrefs;
class PermissionHelper;
struct WebRequestInfo;
namespace declarative_net_request {
class CompositeMatcher;
struct RequestAction;
struct RequestParams;
class RulesetManager {
public:
explicit RulesetManager(content::BrowserContext* browser_context);
RulesetManager(const RulesetManager&) = delete;
RulesetManager& operator=(const RulesetManager&) = delete;
~RulesetManager();
class TestObserver {
public:
virtual void OnEvaluateRequest(const WebRequestInfo& request,
bool is_incognito_context) {}
virtual void OnRulesetCountChanged(size_t new_count) {}
protected:
virtual ~TestObserver() {}
};
void AddRuleset(const ExtensionId& extension_id,
std::unique_ptr<CompositeMatcher> matcher);
void RemoveRuleset(const ExtensionId& extension_id);
std::set<ExtensionId> GetExtensionsWithRulesets() const;
CompositeMatcher* GetMatcherForExtension(const ExtensionId& extension_id);
const CompositeMatcher* GetMatcherForExtension(
const ExtensionId& extension_id) const;
const std::vector<RequestAction>& EvaluateBeforeRequest(
const WebRequestInfo& request,
bool is_incognito_context) const;
std::vector<RequestAction> EvaluateRequestWithHeaders(
const WebRequestInfo& request,
const net::HttpResponseHeaders* response_headers,
bool is_incognito_context) const;
bool HasAnyExtraHeadersMatcher() const;
bool HasExtraHeadersMatcherForRequest(const WebRequestInfo& request,
bool is_incognito_context) const;
void OnRenderFrameCreated(content::RenderFrameHost* host);
void OnRenderFrameDeleted(content::RenderFrameHost* host);
void OnDidFinishNavigation(content::NavigationHandle* navigation_handle);
bool HasRulesets(RulesetMatchingStage stage) const;
std::vector<RequestAction> MergeModifyHeaderActions(
std::vector<RequestAction> lhs_actions,
std::vector<RequestAction> rhs_actions) const;
size_t GetMatcherCountForTest() const { return rulesets_.size(); }
void SetObserverForTest(TestObserver* observer);
private:
struct ExtensionRulesetData {
ExtensionRulesetData(const ExtensionId& extension_id,
const base::Time& extension_install_time,
std::unique_ptr<CompositeMatcher> matcher);
ExtensionRulesetData(const ExtensionRulesetData&) = delete;
ExtensionRulesetData(ExtensionRulesetData&& other);
ExtensionRulesetData& operator=(const ExtensionRulesetData&) = delete;
ExtensionRulesetData& operator=(ExtensionRulesetData&& other);
~ExtensionRulesetData();
ExtensionId extension_id;
base::Time extension_install_time;
std::unique_ptr<CompositeMatcher> matcher;
bool operator<(const ExtensionRulesetData& other) const;
};
using RulesetAndPageAccess =
std::pair<const ExtensionRulesetData*, PermissionsData::PageAccess>;
std::optional<RequestAction> GetAction(
const std::vector<RulesetAndPageAccess>& rulesets,
const WebRequestInfo& request,
const RequestParams& params,
RulesetMatchingStage stage) const;
std::vector<RequestAction> GetModifyHeadersActions(
const std::vector<RulesetAndPageAccess>& rulesets,
const WebRequestInfo& request,
const RequestParams& params,
RulesetMatchingStage stage) const;
std::vector<RequestAction> EvaluateRequestInternal(
const WebRequestInfo& request,
const net::HttpResponseHeaders* response_headers,
bool is_incognito_context) const;
bool ShouldEvaluateRequest(const WebRequestInfo& request) const;
bool ShouldEvaluateRulesetForRequest(
const ExtensionRulesetData& ruleset,
const WebRequestInfo& request,
bool is_incognito_context,
PermissionsData::PageAccess& host_permission_access) const;
base::flat_set<ExtensionRulesetData> rulesets_;
std::map<ExtensionId, base::Time> extension_install_times_;
const raw_ptr<content::BrowserContext> browser_context_;
const raw_ptr<ExtensionPrefs> prefs_;
const raw_ptr<PermissionHelper> permission_helper_;
raw_ptr<TestObserver> test_observer_ = nullptr;
SEQUENCE_CHECKER(sequence_checker_);
};
}
}
#endif