Commit f13c06b9 authored by Sam Burnett's avatar Sam Burnett Committed by Commit Bot

ReportingService: Load state from the PersistentReportingStore

Bug: 895821
Change-Id: If34c7c76d59d713a57fac8d9901f3549f990a7a8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1704680
Commit-Queue: Lily Chen <chlily@chromium.org>
Reviewed-by: default avatarChristian Dullweber <dullweber@chromium.org>
Reviewed-by: default avatarLily Chen <chlily@chromium.org>
Cr-Commit-Position: refs/heads/master@{#682295}
parent b9d88681
...@@ -5,29 +5,80 @@ ...@@ -5,29 +5,80 @@
#include "net/reporting/mock_persistent_reporting_store.h" #include "net/reporting/mock_persistent_reporting_store.h"
#include <algorithm> #include <algorithm>
#include <memory>
namespace net { namespace net {
MockPersistentReportingStore::Command::Command( MockPersistentReportingStore::Command::Command(
Type type, Type type,
ReportingClientsLoadedCallback loaded_callback) ReportingClientsLoadedCallback loaded_callback)
: type(type), loaded_callback(std::move(loaded_callback)) {} : type(type), loaded_callback(std::move(loaded_callback)) {
DCHECK(type == Type::LOAD_REPORTING_CLIENTS);
}
MockPersistentReportingStore::Command::Command( MockPersistentReportingStore::Command::Command(
Type type, Type type,
const ReportingEndpoint& endpoint) const ReportingEndpoint& endpoint)
: type(type), group_key(endpoint.group_key), url(endpoint.info.url) {} : type(type), group_key(endpoint.group_key), url(endpoint.info.url) {
DCHECK(type == Type::ADD_REPORTING_ENDPOINT ||
type == Type::UPDATE_REPORTING_ENDPOINT_DETAILS ||
type == Type::DELETE_REPORTING_ENDPOINT);
}
MockPersistentReportingStore::Command::Command(Type type,
const GURL& origin,
const std::string& group,
const GURL& endpoint)
: MockPersistentReportingStore::Command(type,
url::Origin::Create(origin),
group,
endpoint) {}
MockPersistentReportingStore::Command::Command(Type type,
const url::Origin& origin,
const std::string& group,
const GURL& endpoint)
: MockPersistentReportingStore::Command(
type,
ReportingEndpoint(origin,
group,
ReportingEndpoint::EndpointInfo{endpoint})) {}
MockPersistentReportingStore::Command::Command( MockPersistentReportingStore::Command::Command(
Type type, Type type,
const CachedReportingEndpointGroup& group) const CachedReportingEndpointGroup& group)
: type(type), group_key(group.group_key) {} : type(type), group_key(group.group_key) {
DCHECK(type == Type::ADD_REPORTING_ENDPOINT_GROUP ||
type == Type::UPDATE_REPORTING_ENDPOINT_GROUP_DETAILS ||
type == Type::UPDATE_REPORTING_ENDPOINT_GROUP_ACCESS_TIME ||
type == Type::DELETE_REPORTING_ENDPOINT_GROUP);
}
MockPersistentReportingStore::Command::Command(Type type) : type(type) {} MockPersistentReportingStore::Command::Command(Type type) : type(type) {
DCHECK(type == Type::FLUSH || type == Type::LOAD_REPORTING_CLIENTS);
}
MockPersistentReportingStore::Command::Command(const Command& other) MockPersistentReportingStore::Command::Command(const Command& other)
: type(other.type), group_key(other.group_key), url(other.url) {} : type(other.type), group_key(other.group_key), url(other.url) {}
MockPersistentReportingStore::Command::Command(Type type,
const GURL& origin,
const std::string& group)
: MockPersistentReportingStore::Command(type,
url::Origin::Create(origin),
group) {}
MockPersistentReportingStore::Command::Command(Type type,
const url::Origin& origin,
const std::string& group)
: MockPersistentReportingStore::Command(
type,
CachedReportingEndpointGroup(origin,
group,
OriginSubdomains::DEFAULT /* unused */,
base::Time() /* unused */,
base::Time() /* unused */)) {}
MockPersistentReportingStore::Command::Command(Command&& other) = default; MockPersistentReportingStore::Command::Command(Command&& other) = default;
MockPersistentReportingStore::Command::~Command() = default; MockPersistentReportingStore::Command::~Command() = default;
...@@ -68,6 +119,52 @@ bool operator!=(const MockPersistentReportingStore::Command& lhs, ...@@ -68,6 +119,52 @@ bool operator!=(const MockPersistentReportingStore::Command& lhs,
return !(lhs == rhs); return !(lhs == rhs);
} }
std::ostream& operator<<(std::ostream& out,
const MockPersistentReportingStore::Command& cmd) {
switch (cmd.type) {
case MockPersistentReportingStore::Command::Type::LOAD_REPORTING_CLIENTS:
return out << "LOAD_REPORTING_CLIENTS()";
case MockPersistentReportingStore::Command::Type::FLUSH:
return out << "FLUSH()";
case MockPersistentReportingStore::Command::Type::ADD_REPORTING_ENDPOINT:
return out << "ADD_REPORTING_ENDPOINT("
<< "origin=" << cmd.group_key.origin << ", "
<< "group=" << cmd.group_key.group_name << ", "
<< "endpoint=" << cmd.url << ")";
case MockPersistentReportingStore::Command::Type::
UPDATE_REPORTING_ENDPOINT_DETAILS:
return out << "UPDATE_REPORTING_ENDPOINT_DETAILS("
<< "origin=" << cmd.group_key.origin << ", "
<< "group=" << cmd.group_key.group_name << ", "
<< "endpoint=" << cmd.url << ")";
case MockPersistentReportingStore::Command::Type::DELETE_REPORTING_ENDPOINT:
return out << "DELETE_REPORTING_ENDPOINT("
<< "origin=" << cmd.group_key.origin << ", "
<< "group=" << cmd.group_key.group_name << ", "
<< "endpoint=" << cmd.url << ")";
case MockPersistentReportingStore::Command::Type::
ADD_REPORTING_ENDPOINT_GROUP:
return out << "ADD_REPORTING_ENDPOINT_GROUP("
<< "origin=" << cmd.group_key.origin << ", "
<< "group=" << cmd.group_key.group_name << ")";
case MockPersistentReportingStore::Command::Type::
UPDATE_REPORTING_ENDPOINT_GROUP_ACCESS_TIME:
return out << "UPDATE_REPORTING_ENDPOINT_GROUP_ACCESS_TIME("
<< "origin=" << cmd.group_key.origin << ", "
<< "group=" << cmd.group_key.group_name << ")";
case MockPersistentReportingStore::Command::Type::
UPDATE_REPORTING_ENDPOINT_GROUP_DETAILS:
return out << "UPDATE_REPORTING_ENDPOINT_GROUP_DETAILS("
<< "origin=" << cmd.group_key.origin << ", "
<< "group=" << cmd.group_key.group_name << ")";
case MockPersistentReportingStore::Command::Type::
DELETE_REPORTING_ENDPOINT_GROUP:
return out << "DELETE_REPORTING_ENDPOINT_GROUP("
<< "origin=" << cmd.group_key.origin << ", "
<< "group=" << cmd.group_key.group_name << ")";
}
}
MockPersistentReportingStore::MockPersistentReportingStore() MockPersistentReportingStore::MockPersistentReportingStore()
: load_started_(false), : load_started_(false),
endpoint_count_(0), endpoint_count_(0),
......
...@@ -40,11 +40,27 @@ class MockPersistentReportingStore ...@@ -40,11 +40,27 @@ class MockPersistentReportingStore
// Constructor for LOAD_REPORTING_CLIENTS commands. // Constructor for LOAD_REPORTING_CLIENTS commands.
Command(Type type, ReportingClientsLoadedCallback loaded_callback); Command(Type type, ReportingClientsLoadedCallback loaded_callback);
// Constructor for endpoint commands. // Constructors for endpoint commands. |type| must be one of
// ADD_REPORTING_ENDPOINT, UPDATE_REPORTING_ENDPOINT_DETAILS, or
// DELETE_REPORTING_ENDPOINT
Command(Type type, const ReportingEndpoint& endpoint); Command(Type type, const ReportingEndpoint& endpoint);
// Constructor for endpoint group commands. Command(Type type,
const GURL& origin,
const std::string& group,
const GURL& endpoint);
Command(Type type,
const url::Origin& origin,
const std::string& group,
const GURL& endpoint);
// Constructors for endpoint group commands. |type| must be one of
// ADD_REPORTING_ENDPOINT_GROUP,
// UPDATE_REPORTING_ENDPOINT_GROUP_ACCESS_TIME,
// UPDATE_REPORTING_ENDPOINT_GROUP_DETAILS, or
// DELETE_REPORTING_ENDPOINT_GROUP
Command(Type type, const CachedReportingEndpointGroup& group); Command(Type type, const CachedReportingEndpointGroup& group);
// Constructor for FLUSH commands. Command(Type type, const GURL& origin, const std::string& group);
Command(Type type, const url::Origin& origin, const std::string& group);
// |type| must be LOAD_REPORTING_CLIENTS or FLUSH.
Command(Type type); Command(Type type);
Command(const Command& other); Command(const Command& other);
...@@ -147,6 +163,8 @@ bool operator==(const MockPersistentReportingStore::Command& lhs, ...@@ -147,6 +163,8 @@ bool operator==(const MockPersistentReportingStore::Command& lhs,
const MockPersistentReportingStore::Command& rhs); const MockPersistentReportingStore::Command& rhs);
bool operator!=(const MockPersistentReportingStore::Command& lhs, bool operator!=(const MockPersistentReportingStore::Command& lhs,
const MockPersistentReportingStore::Command& rhs); const MockPersistentReportingStore::Command& rhs);
std::ostream& operator<<(std::ostream& out,
const MockPersistentReportingStore::Command& cmd);
} // namespace net } // namespace net
......
...@@ -38,6 +38,7 @@ void ReportingBrowsingDataRemover::RemoveBrowsingData( ...@@ -38,6 +38,7 @@ void ReportingBrowsingDataRemover::RemoveBrowsingData(
cache->RemoveClient(origin); cache->RemoveClient(origin);
} }
} }
cache->Flush();
} }
// static // static
...@@ -50,6 +51,7 @@ void ReportingBrowsingDataRemover::RemoveAllBrowsingData(ReportingCache* cache, ...@@ -50,6 +51,7 @@ void ReportingBrowsingDataRemover::RemoveAllBrowsingData(ReportingCache* cache,
if ((data_type_mask & DATA_TYPE_CLIENTS) != 0) { if ((data_type_mask & DATA_TYPE_CLIENTS) != 0) {
cache->RemoveAllClients(); cache->RemoveAllClients();
} }
cache->Flush();
} }
} // namespace net } // namespace net
...@@ -199,6 +199,9 @@ class NET_EXPORT ReportingCache { ...@@ -199,6 +199,9 @@ class NET_EXPORT ReportingCache {
// Gets the total number of endpoints in the cache across all origins. // Gets the total number of endpoints in the cache across all origins.
virtual size_t GetEndpointCount() const = 0; virtual size_t GetEndpointCount() const = 0;
// Flush the contents of the cache to disk, if applicable.
virtual void Flush() = 0;
// Finds an endpoint for the given |origin|, |group_name|, and |url|, // Finds an endpoint for the given |origin|, |group_name|, and |url|,
// otherwise returns an invalid ReportingEndpoint. // otherwise returns an invalid ReportingEndpoint.
virtual ReportingEndpoint GetEndpointForTesting(const url::Origin& origin, virtual ReportingEndpoint GetEndpointForTesting(const url::Origin& origin,
......
...@@ -554,6 +554,11 @@ size_t ReportingCacheImpl::GetEndpointCount() const { ...@@ -554,6 +554,11 @@ size_t ReportingCacheImpl::GetEndpointCount() const {
return endpoints_.size(); return endpoints_.size();
} }
void ReportingCacheImpl::Flush() {
if (context_->IsClientDataPersisted())
store()->Flush();
}
ReportingEndpoint ReportingCacheImpl::GetEndpointForTesting( ReportingEndpoint ReportingCacheImpl::GetEndpointForTesting(
const url::Origin& origin, const url::Origin& origin,
const std::string& group_name, const std::string& group_name,
......
...@@ -84,6 +84,7 @@ class ReportingCacheImpl : public ReportingCache { ...@@ -84,6 +84,7 @@ class ReportingCacheImpl : public ReportingCache {
const std::string& group_name) override; const std::string& group_name) override;
base::Value GetClientsAsValue() const override; base::Value GetClientsAsValue() const override;
size_t GetEndpointCount() const override; size_t GetEndpointCount() const override;
void Flush() override;
ReportingEndpoint GetEndpointForTesting(const url::Origin& origin, ReportingEndpoint GetEndpointForTesting(const url::Origin& origin,
const std::string& group_name, const std::string& group_name,
const GURL& url) const override; const GURL& url) const override;
......
...@@ -87,8 +87,6 @@ bool ReportingContext::IsClientDataPersisted() const { ...@@ -87,8 +87,6 @@ bool ReportingContext::IsClientDataPersisted() const {
void ReportingContext::OnShutdown() { void ReportingContext::OnShutdown() {
uploader_->OnShutdown(); uploader_->OnShutdown();
if (store_)
store_->Flush();
} }
ReportingContext::ReportingContext( ReportingContext::ReportingContext(
......
...@@ -28,14 +28,28 @@ namespace { ...@@ -28,14 +28,28 @@ namespace {
constexpr int kMaxJsonSize = 16 * 1024; constexpr int kMaxJsonSize = 16 * 1024;
constexpr int kMaxJsonDepth = 5; constexpr int kMaxJsonDepth = 5;
// If constructed with a PersistentReportingStore, the first call to any of
// QueueReport(), ProcessHeader(), RemoveBrowsingData(), or
// RemoveAllBrowsingData() on a valid input will trigger a load from the store.
// Tasks are queued pending completion of loading from the store.
class ReportingServiceImpl : public ReportingService { class ReportingServiceImpl : public ReportingService {
public: public:
ReportingServiceImpl(std::unique_ptr<ReportingContext> context) ReportingServiceImpl(std::unique_ptr<ReportingContext> context)
: context_(std::move(context)), shut_down_(false) {} : context_(std::move(context)),
shut_down_(false),
started_loading_from_store_(false),
initialized_(false),
weak_factory_(this) {
if (!context_->IsClientDataPersisted())
initialized_ = true;
}
// ReportingService implementation: // ReportingService implementation:
~ReportingServiceImpl() override = default; ~ReportingServiceImpl() override {
if (initialized_)
context_->cache()->Flush();
}
void QueueReport(const GURL& url, void QueueReport(const GURL& url,
const std::string& user_agent, const std::string& user_agent,
...@@ -43,9 +57,6 @@ class ReportingServiceImpl : public ReportingService { ...@@ -43,9 +57,6 @@ class ReportingServiceImpl : public ReportingService {
const std::string& type, const std::string& type,
std::unique_ptr<const base::Value> body, std::unique_ptr<const base::Value> body,
int depth) override { int depth) override {
if (shut_down_)
return;
DCHECK(context_); DCHECK(context_);
DCHECK(context_->delegate()); DCHECK(context_->delegate());
...@@ -57,16 +68,18 @@ class ReportingServiceImpl : public ReportingService { ...@@ -57,16 +68,18 @@ class ReportingServiceImpl : public ReportingService {
if (!sanitized_url.is_valid()) if (!sanitized_url.is_valid())
return; return;
context_->cache()->AddReport(sanitized_url, user_agent, group, type, base::TimeTicks queued_ticks = context_->tick_clock().NowTicks();
std::move(body), depth,
context_->tick_clock().NowTicks(), 0); // base::Unretained is safe because the callback is stored in
// |task_backlog_| which will not outlive |this|.
DoOrBacklogTask(base::BindOnce(&ReportingServiceImpl::DoQueueReport,
base::Unretained(this),
std::move(sanitized_url), user_agent, group,
type, std::move(body), depth, queued_ticks));
} }
void ProcessHeader(const GURL& url, void ProcessHeader(const GURL& url,
const std::string& header_string) override { const std::string& header_string) override {
if (shut_down_)
return;
if (header_string.size() > kMaxJsonSize) { if (header_string.size() > kMaxJsonSize) {
ReportingHeaderParser::RecordHeaderDiscardedForJsonTooBig(); ReportingHeaderParser::RecordHeaderDiscardedForJsonTooBig();
return; return;
...@@ -81,20 +94,23 @@ class ReportingServiceImpl : public ReportingService { ...@@ -81,20 +94,23 @@ class ReportingServiceImpl : public ReportingService {
} }
DVLOG(1) << "Received Reporting policy for " << url.GetOrigin(); DVLOG(1) << "Received Reporting policy for " << url.GetOrigin();
ReportingHeaderParser::ParseHeader(context_.get(), url, DoOrBacklogTask(base::BindOnce(&ReportingServiceImpl::DoProcessHeader,
std::move(header_value)); base::Unretained(this), url,
std::move(header_value)));
} }
void RemoveBrowsingData(int data_type_mask, void RemoveBrowsingData(int data_type_mask,
const base::RepeatingCallback<bool(const GURL&)>& const base::RepeatingCallback<bool(const GURL&)>&
origin_filter) override { origin_filter) override {
ReportingBrowsingDataRemover::RemoveBrowsingData( DoOrBacklogTask(base::BindOnce(&ReportingServiceImpl::DoRemoveBrowsingData,
context_->cache(), data_type_mask, origin_filter); base::Unretained(this), data_type_mask,
origin_filter));
} }
void RemoveAllBrowsingData(int data_type_mask) override { void RemoveAllBrowsingData(int data_type_mask) override {
ReportingBrowsingDataRemover::RemoveAllBrowsingData(context_->cache(), DoOrBacklogTask(
data_type_mask); base::BindOnce(&ReportingServiceImpl::DoRemoveAllBrowsingData,
base::Unretained(this), data_type_mask));
} }
void OnShutdown() override { void OnShutdown() override {
...@@ -119,8 +135,98 @@ class ReportingServiceImpl : public ReportingService { ...@@ -119,8 +135,98 @@ class ReportingServiceImpl : public ReportingService {
} }
private: private:
void DoOrBacklogTask(base::OnceClosure task) {
if (shut_down_)
return;
FetchAllClientsFromStoreIfNecessary();
if (!initialized_) {
task_backlog_.push_back(std::move(task));
return;
}
std::move(task).Run();
}
void DoQueueReport(GURL sanitized_url,
const std::string& user_agent,
const std::string& group,
const std::string& type,
std::unique_ptr<const base::Value> body,
int depth,
base::TimeTicks queued_ticks) {
DCHECK(initialized_);
context_->cache()->AddReport(sanitized_url, user_agent, group, type,
std::move(body), depth, queued_ticks,
0 /* attempts */);
}
void DoProcessHeader(const GURL& url,
std::unique_ptr<base::Value> header_value) {
DCHECK(initialized_);
ReportingHeaderParser::ParseHeader(context_.get(), url,
std::move(header_value));
}
void DoRemoveBrowsingData(
int data_type_mask,
const base::RepeatingCallback<bool(const GURL&)>& origin_filter) {
DCHECK(initialized_);
ReportingBrowsingDataRemover::RemoveBrowsingData(
context_->cache(), data_type_mask, origin_filter);
}
void DoRemoveAllBrowsingData(int data_type_mask) {
DCHECK(initialized_);
ReportingBrowsingDataRemover::RemoveAllBrowsingData(context_->cache(),
data_type_mask);
}
void ExecuteBacklog() {
DCHECK(initialized_);
DCHECK(context_);
if (shut_down_)
return;
for (base::OnceClosure& task : task_backlog_) {
std::move(task).Run();
}
task_backlog_.clear();
}
void FetchAllClientsFromStoreIfNecessary() {
if (!context_->IsClientDataPersisted() || started_loading_from_store_)
return;
started_loading_from_store_ = true;
FetchAllClientsFromStore();
}
void FetchAllClientsFromStore() {
DCHECK(context_->IsClientDataPersisted());
DCHECK(!initialized_);
context_->store()->LoadReportingClients(base::BindOnce(
&ReportingServiceImpl::OnClientsLoaded, weak_factory_.GetWeakPtr()));
}
void OnClientsLoaded(
std::vector<ReportingEndpoint> loaded_endpoints,
std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups) {
initialized_ = true;
context_->cache()->AddClientsLoadedFromStore(
std::move(loaded_endpoints), std::move(loaded_endpoint_groups));
ExecuteBacklog();
}
std::unique_ptr<ReportingContext> context_; std::unique_ptr<ReportingContext> context_;
bool shut_down_; bool shut_down_;
bool started_loading_from_store_;
bool initialized_;
std::vector<base::OnceClosure> task_backlog_;
base::WeakPtrFactory<ReportingServiceImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ReportingServiceImpl); DISALLOW_COPY_AND_ASSIGN(ReportingServiceImpl);
}; };
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment