File: lookup_affiliation_response_parser.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (136 lines) | stat: -rw-r--r-- 4,845 bytes parent folder | download | duplicates (5)
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