Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Unified Diff: net/reporting/reporting_delivery_agent.cc

Issue 2739483002: Reporting: Implement delivery agent. (Closed)
Patch Set: Make requested changes. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/reporting/reporting_delivery_agent.cc
diff --git a/net/reporting/reporting_delivery_agent.cc b/net/reporting/reporting_delivery_agent.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f2ce3c76f262d159aec76454cbed28638bd5b8d6
--- /dev/null
+++ b/net/reporting/reporting_delivery_agent.cc
@@ -0,0 +1,149 @@
+// 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.
+
+#include "net/reporting/reporting_delivery_agent.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/json/json_writer.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/time/tick_clock.h"
+#include "base/values.h"
+#include "net/reporting/reporting_cache.h"
+#include "net/reporting/reporting_endpoint_manager.h"
+#include "net/reporting/reporting_report.h"
+#include "net/reporting/reporting_uploader.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace net {
+
+namespace {
+
+std::string SerializeReports(const std::vector<const ReportingReport*>& reports,
+ base::TimeTicks now) {
+ base::ListValue reports_value;
+
+ for (const ReportingReport* report : reports) {
+ std::unique_ptr<base::DictionaryValue> report_value =
+ base::MakeUnique<base::DictionaryValue>();
+
+ report_value->SetInteger("age", (now - report->queued).InMilliseconds());
+ report_value->SetString("type", report->type);
+ report_value->SetString("url", report->url.spec());
+ report_value->Set("report", report->body->DeepCopy());
shivanisha 2017/03/31 18:58:51 Does "group" need to be set as well? May be a add
Julia Tuttle 2017/04/04 18:09:31 No, group just determines which endpoints the repo
+
+ reports_value.Append(std::move(report_value));
+ }
+
+ std::string reports_json = "";
+ bool json_written = base::JSONWriter::Write(reports_value, &reports_json);
+ DCHECK(json_written);
+
+ return reports_json;
+}
+
+} // namespace
+
+ReportingDeliveryAgent::ReportingDeliveryAgent(
+ base::TickClock* clock,
+ ReportingCache* cache,
+ ReportingUploader* uploader,
+ const BackoffEntry::Policy* endpoint_backoff_policy)
+ : clock_(clock),
+ cache_(cache),
+ uploader_(uploader),
+ endpoint_manager_(clock, cache, endpoint_backoff_policy),
+ weak_factory_(this) {}
+ReportingDeliveryAgent::~ReportingDeliveryAgent() {}
+
+class ReportingDeliveryAgent::Delivery {
+ public:
+ Delivery(const GURL& endpoint,
+ const std::vector<const ReportingReport*>& reports)
+ : endpoint(endpoint), reports(reports) {}
+
+ ~Delivery() {}
+
+ const GURL endpoint;
+ const std::vector<const ReportingReport*> reports;
+};
+
+void ReportingDeliveryAgent::SendReports() {
+ std::vector<const ReportingReport*> reports;
+ cache_->GetReports(&reports);
+
+ // Sort reports into (origin, group) buckets.
+ std::map<OriginGroup, std::vector<const ReportingReport*>>
+ origin_group_reports;
+ for (const ReportingReport* report : reports) {
+ OriginGroup origin_group(url::Origin(report->url), report->group);
+ origin_group_reports[origin_group].push_back(report);
+ }
+
+ // Find endpoint for each (origin, group) bucket and sort reports into
+ // endpoint buckets. Don't allow concurrent deliveries to the same (origin,
+ // group) bucket.
+ std::map<GURL, std::vector<const ReportingReport*>> endpoint_reports;
+ for (auto& it : origin_group_reports) {
+ const OriginGroup& origin_group = it.first;
+
+ if (base::ContainsKey(pending_origin_groups_, origin_group))
shivanisha 2017/03/31 18:58:51 nit: To me it seems more consistent to use std:: m
Julia Tuttle 2017/04/04 18:09:31 jkarlin suggested "base::ContainsKey(collection, k
+ continue;
+
+ GURL endpoint_url;
+ if (!endpoint_manager_.FindEndpointForOriginAndGroup(
+ origin_group.first, origin_group.second, &endpoint_url)) {
+ continue;
+ }
+
+ endpoint_reports[endpoint_url].insert(endpoint_reports[endpoint_url].end(),
+ it.second.begin(), it.second.end());
+ pending_origin_groups_.insert(origin_group);
+ }
+
+ // Start a delivery to each endpoint.
+ for (auto& it : endpoint_reports) {
+ const GURL& endpoint = it.first;
+ const std::vector<const ReportingReport*>& reports = it.second;
+
+ endpoint_manager_.SetEndpointPending(endpoint);
+ cache_->SetReportsPending(reports);
+
+ uploader_->StartUpload(
+ endpoint, SerializeReports(reports, clock_->NowTicks()),
+ base::Bind(&ReportingDeliveryAgent::OnUploadComplete,
+ weak_factory_.GetWeakPtr(),
+ base::MakeUnique<Delivery>(endpoint, reports)));
+ }
+}
+
+void ReportingDeliveryAgent::OnUploadComplete(
+ const std::unique_ptr<Delivery>& delivery,
+ ReportingUploader::Outcome outcome) {
+ if (outcome == ReportingUploader::Outcome::SUCCESS) {
+ cache_->RemoveReports(delivery->reports);
+ endpoint_manager_.InformOfEndpointRequest(delivery->endpoint, true);
+ } else {
+ cache_->IncrementReportsAttempts(delivery->reports);
+ endpoint_manager_.InformOfEndpointRequest(delivery->endpoint, false);
+ }
+
+ if (outcome == ReportingUploader::Outcome::REMOVE_ENDPOINT)
+ cache_->RemoveClientsForEndpoint(delivery->endpoint);
+
+ for (const ReportingReport* report : delivery->reports) {
+ pending_origin_groups_.erase(
+ OriginGroup(url::Origin(report->url), report->group));
+ }
+
+ cache_->ClearReportsPending(delivery->reports);
+ endpoint_manager_.ClearEndpointPending(delivery->endpoint);
+}
+
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698