1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/affiliations/core/browser/lookup_affiliation_response_parser.h"
#include "base/containers/flat_set.h"
namespace affiliations {
namespace {
// Template for the affiliation_pb message:
// > affiliation_pb::Affiliation
// > affiliation_pb::FacetGroup
template <typename MessageT>
std::vector<Facet> ParseFacets(const MessageT& response) {
std::vector<Facet> facets;
facets.reserve(response.facet().size());
for (const auto& facet : response.facet()) {
const std::string& uri_spec(facet.id());
FacetURI uri = FacetURI::FromPotentiallyInvalidSpec(uri_spec);
// Ignore potential future kinds of facet URIs (e.g. for new platforms).
if (!uri.is_valid())
continue;
Facet new_facet(uri);
if (facet.has_branding_info()) {
new_facet.branding_info = FacetBrandingInfo{
facet.branding_info().name(), GURL(facet.branding_info().icon_url())};
}
if (facet.has_change_password_info()) {
new_facet.change_password_url =
GURL(facet.change_password_info().change_password_url());
}
if (facet.has_main_domain()) {
new_facet.main_domain = facet.main_domain();
}
facets.push_back(std::move(new_facet));
}
return facets;
}
AffiliatedFacets ParseEqClass(const affiliation_pb::Affiliation& affiliation) {
return ParseFacets(affiliation);
}
GroupedFacets ParseEqClass(const affiliation_pb::FacetGroup& grouping) {
GroupedFacets group;
group.facets = ParseFacets(grouping);
if (grouping.has_group_branding_info()) {
group.branding_info =
FacetBrandingInfo{grouping.group_branding_info().name(),
GURL(grouping.group_branding_info().icon_url())};
}
return group;
}
void AddSingleFacet(std::vector<AffiliatedFacets>& affiliations, Facet facet) {
affiliations.push_back({facet});
}
void AddSingleFacet(std::vector<GroupedFacets>& groups, Facet facet) {
GroupedFacets group;
group.facets = {facet};
groups.push_back(std::move(group));
}
// Template for the affiliation_pb message:
// > affiliation_pb::Affiliation
// > affiliation_pb::FacetGroup
template <typename MessageT, typename ResultT>
bool ParseResponse(const std::vector<FacetURI>& requested_facet_uris,
const MessageT& response,
ResultT& result) {
std::map<std::string, size_t> facet_uri_to_class_index;
base::flat_set<std::string> requested_facets = base::MakeFlatSet<std::string>(
requested_facet_uris, /*comp=*/{}, &FacetURI::potentially_invalid_spec);
// Validate and de-duplicate data.
for (const auto& equivalence_class : response) {
// Be lenient and ignore empty (after filtering) equivalence classes.
if (equivalence_class.facet().empty())
continue;
// Ignore equivalence classes that are duplicates of earlier ones. However,
// fail in the case of a partial overlap, which violates the invariant that
// affiliations must form an equivalence relation. Also check, if the class
// was requested.
bool is_class_requested = false;
for (const auto& facet : equivalence_class.facet()) {
if (requested_facets.count(facet.id()))
is_class_requested = true;
if (!facet_uri_to_class_index.count(facet.id()))
facet_uri_to_class_index[facet.id()] = result.size();
if (facet_uri_to_class_index[facet.id()] !=
facet_uri_to_class_index[equivalence_class.facet()[0].id()]) {
return false;
}
}
// Filter out duplicate or unrequested equivalence classes in the response.
if (is_class_requested &&
facet_uri_to_class_index[equivalence_class.facet()[0].id()] ==
result.size()) {
result.push_back(ParseEqClass(equivalence_class));
}
}
// Synthesize an equivalence class (of size one) for each facet that did not
// appear in the server response due to not being affiliated with any others.
for (const FacetURI& uri : requested_facet_uris) {
if (!facet_uri_to_class_index.count(uri.potentially_invalid_spec()))
AddSingleFacet(result, Facet(uri));
}
return true;
}
} // namespace
bool ParseLookupAffiliationResponse(
const std::vector<FacetURI>& requested_facet_uris,
const affiliation_pb::LookupAffiliationByHashPrefixResponse& response,
AffiliationFetcherInterface::ParsedFetchResponse* result) {
for (const auto& domain : response.psl_extensions()) {
result->psl_extensions.push_back(domain);
}
return ParseResponse(requested_facet_uris, response.affiliations(),
result->affiliations) &&
ParseResponse(requested_facet_uris, response.groups(),
result->groupings);
}
} // namespace affiliations
|