File: data_upload_config_downloader.cc

package info (click to toggle)
chromium 141.0.7390.107-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 6,246,132 kB
  • sloc: cpp: 35,264,965; ansic: 7,169,920; javascript: 4,250,185; python: 1,460,635; asm: 950,788; xml: 751,751; pascal: 187,972; sh: 89,459; perl: 88,691; objc: 79,953; sql: 53,924; cs: 44,622; fortran: 24,137; makefile: 22,313; tcl: 15,277; php: 14,018; yacc: 8,995; ruby: 7,553; awk: 3,720; lisp: 3,096; lex: 1,330; ada: 727; jsp: 228; sed: 36
file content (147 lines) | stat: -rw-r--r-- 5,681 bytes parent folder | download | duplicates (4)
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
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2025 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/metrics/private_metrics/data_upload_config_downloader.h"

#include <memory>

#include "net/http/http_status_code.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "url/gurl.h"

namespace metrics::private_metrics {

namespace {
constexpr size_t kMaxDownloadBytes = 50 * 1024;  // 50 KB

// Max number of retries for fetching the configuration.
constexpr int kMaxRetries = 3;

// The conditions for which a retry will trigger.
constexpr int kRetryMode = network::SimpleURLLoader::RETRY_ON_5XX |
                           network::SimpleURLLoader::RETRY_ON_NETWORK_CHANGE |
                           network::SimpleURLLoader::RETRY_ON_NAME_NOT_RESOLVED;

constexpr net::NetworkTrafficAnnotationTag kPrivateMetricsKeyNetworkTag =
    net::DefineNetworkTrafficAnnotation("private_metrics_encryption_key", R"(
        semantics {
          sender: "Private Metrics Encryption Key"
          description:
            "Retrieves a public key and its signed endorsements in the form "
            "of a serialized DataUploadConfig. The public key will be used to "
            "encrypt PrivateMetricReport prior to uploading to Google "
            "servers. The private key will only be granted in a trusted "
            "execution environment, and the signed endorsements can be used "
            "to verify the attestation."
          trigger:
            "Private Metric encryption keys will automatically be fetched "
            "while Chrome is running with usage statistics and 'Make searches "
            "and browsing better' settings enabled."
          data: "None"
          user_data {
            type: NONE
          }
          internal {
            contacts {
              email: "//components/metrics/OWNERS"
            }
          }
          destination: GOOGLE_OWNED_SERVICE
          last_reviewed: "2025-08-21"
        }
        policy {
         cookies_allowed: NO
         setting:
            "Users can enable or disable this feature by disabling 'Make "
            "searches and browsing better' in Chrome's settings under Advanced "
            "Settings, Privacy. This has to be enabled for all active "
            "profiles. This is only enabled if the user has 'Help improve "
            "Chrome's features and performance' enabled in the same settings "
            "menu."
        chrome_policy {
          MetricsReportingEnabled {
            policy_options {mode: MANDATORY}
            MetricsReportingEnabled: false
          }
          UrlKeyedAnonymizedDataCollectionEnabled {
            policy_options {mode: MANDATORY}
            UrlKeyedAnonymizedDataCollectionEnabled: false
          }
        }
        })");

inline constexpr char kDataUploadConfigGstaticUrl[] =
    "https://www.gstatic.com/chrome/private-metrics/data-upload-config.pbtxt";
}  // namespace

std::unique_ptr<network::SimpleURLLoader> CreateSimpleURLLoader(
    const GURL& url) {
  auto resource_request = std::make_unique<network::ResourceRequest>();
  resource_request->url = url;
  resource_request->method = "GET";
  resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;

  return network::SimpleURLLoader::Create(std::move(resource_request),
                                          kPrivateMetricsKeyNetworkTag);
}

DataUploadConfigDownloader::DataUploadConfigDownloader(
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
    : url_loader_factory_(url_loader_factory) {}

DataUploadConfigDownloader::~DataUploadConfigDownloader() = default;

void DataUploadConfigDownloader::FetchDataUploadConfig(
    DataUploadConfigCallback callback) {
  if (!url_loader_factory_ || pending_request_) {
    return;
  }

  GURL destination = GURL(kDataUploadConfigGstaticUrl);
  pending_request_ = CreateSimpleURLLoader(destination);
  network::SimpleURLLoader::BodyAsStringCallback handler = base::BindOnce(
      &DataUploadConfigDownloader::HandleSerializedDataUploadConfig,
      self_ptr_factory_.GetWeakPtr(), std::move(callback));
  pending_request_->SetRetryOptions(kMaxRetries, kRetryMode);
  pending_request_->DownloadToString(url_loader_factory_.get(),
                                     std::move(handler), kMaxDownloadBytes);
}

raw_ptr<network::SimpleURLLoader>
DataUploadConfigDownloader::GetPendingRequestForTesting() {
  return pending_request_.get();
}

void DataUploadConfigDownloader::HandleSerializedDataUploadConfig(
    DataUploadConfigCallback callback,
    std::optional<std::string> response_body) {
  if (!pending_request_) {
    return;
  }

  // Move the pending request here so it's deleted when this function ends.
  std::unique_ptr<network::SimpleURLLoader> request =
      std::move(pending_request_);

  // Response code is not 200 or `response_body` is empty.
  if (!request->ResponseInfo() || !request->ResponseInfo()->headers ||
      request->ResponseInfo()->headers->response_code() != net::HTTP_OK ||
      !response_body.has_value() || response_body->empty()) {
    std::move(callback).Run(std::nullopt);
    return;
  }

  fcp::confidentialcompute::DataUploadConfig data_upload_config;
  if (!data_upload_config.ParseFromString(response_body.value())) {
    std::move(callback).Run(std::nullopt);
    return;
  }

  std::move(callback).Run(data_upload_config);
}

}  // namespace metrics::private_metrics