File: sync_stopped_reporter.cc

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,122,156 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 (158 lines) | stat: -rw-r--r-- 5,850 bytes parent folder | download | duplicates (7)
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
148
149
150
151
152
153
154
155
156
157
158
// Copyright 2015 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/sync/service/sync_stopped_reporter.h"

#include <utility>

#include "base/check.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/stringprintf.h"
#include "components/sync/protocol/sync.pb.h"
#include "google_apis/credentials_mode.h"
#include "net/base/load_flags.h"
#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/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/url_response_head.mojom.h"

namespace syncer {

namespace {

const char kEventEndpoint[] = "event";

// The request is tiny, so even on poor connections 10 seconds should be
// plenty of time. Since sync is off when this request is started, we don't
// want anything sync-related hanging around for very long from a human
// perspective either. This seems like a good compromise.
constexpr base::TimeDelta kRequestTimeout = base::Seconds(10);

void LogSyncStoppedRequestTimeout(bool timed_out) {
  base::UmaHistogramBoolean("Sync.SyncStoppedURLFetchTimedOut", timed_out);
}

void LogSyncStoppedRequestResult(const network::SimpleURLLoader& url_loader) {
  int http_status_code = -1;
  if (url_loader.ResponseInfo() && url_loader.ResponseInfo()->headers) {
    http_status_code = url_loader.ResponseInfo()->headers->response_code();
  }
  const int net_error_code = url_loader.NetError();
  const bool request_succeeded =
      net_error_code == net::OK && http_status_code != -1;
  if (request_succeeded) {
    LogSyncStoppedRequestTimeout(/*timed_out=*/false);
  }
  base::UmaHistogramSparse(
      "Sync.SyncStoppedURLFetchResponse",
      request_succeeded ? http_status_code : net_error_code);
}

}  // namespace

SyncStoppedReporter::SyncStoppedReporter(
    const GURL& sync_service_url,
    const std::string& user_agent,
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
    : sync_event_url_(GetSyncEventURL(sync_service_url)),
      user_agent_(user_agent),
      url_loader_factory_(std::move(url_loader_factory)) {
  DCHECK(!sync_service_url.is_empty());
  DCHECK(!user_agent_.empty());
  DCHECK(url_loader_factory_);
}

SyncStoppedReporter::~SyncStoppedReporter() = default;

void SyncStoppedReporter::ReportSyncStopped(const std::string& access_token,
                                            const std::string& cache_guid,
                                            const std::string& birthday) {
  DCHECK(!access_token.empty());
  DCHECK(!cache_guid.empty());
  DCHECK(!birthday.empty());

  // Make the request proto with the GUID identifying this client.
  sync_pb::EventRequest event_request;
  sync_pb::SyncDisabledEvent* sync_disabled_event =
      event_request.mutable_sync_disabled();
  sync_disabled_event->set_cache_guid(cache_guid);
  sync_disabled_event->set_store_birthday(birthday);

  std::string msg;
  event_request.SerializeToString(&msg);

  net::NetworkTrafficAnnotationTag traffic_annotation =
      net::DefineNetworkTrafficAnnotation("sync_stop_reporter", R"(
        semantics {
          sender: "Chrome Sync"
          description:
            "A network request to inform Chrome Sync that sync has been "
            "disabled for this device."
          trigger: "User disables sync."
          data: "Sync device identifier and metadata."
          destination: GOOGLE_OWNED_SERVICE
        }
        policy {
          cookies_allowed: NO
          setting: "This feature cannot be disabled by settings."
          chrome_policy {
            SyncDisabled {
              policy_options {mode: MANDATORY}
              SyncDisabled: true
            }
          }
        })");
  auto resource_request = std::make_unique<network::ResourceRequest>();
  resource_request->url = sync_event_url_;
  resource_request->load_flags =
      net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE;
  resource_request->credentials_mode =
      google_apis::GetOmitCredentialsModeForGaiaRequests();
  resource_request->method = "POST";
  resource_request->headers.SetHeader(
      net::HttpRequestHeaders::kAuthorization,
      base::StringPrintf("Bearer %s", access_token.c_str()));
  resource_request->headers.SetHeader(net::HttpRequestHeaders::kUserAgent,
                                      user_agent_);
  simple_url_loader_ = network::SimpleURLLoader::Create(
      std::move(resource_request), traffic_annotation);
  simple_url_loader_->AttachStringForUpload(msg, "application/octet-stream");
  simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
      url_loader_factory_.get(),
      base::BindOnce(&SyncStoppedReporter::OnSimpleLoaderComplete,
                     base::Unretained(this)));
  timer_.Start(FROM_HERE, kRequestTimeout, this,
               &SyncStoppedReporter::OnTimeout);
}

void SyncStoppedReporter::OnSimpleLoaderComplete(
    std::unique_ptr<std::string> response_body) {
  DCHECK(simple_url_loader_);
  LogSyncStoppedRequestResult(*simple_url_loader_);
  simple_url_loader_.reset();
  timer_.Stop();
}

void SyncStoppedReporter::OnTimeout() {
  LogSyncStoppedRequestTimeout(/*timed_out=*/true);
  simple_url_loader_.reset();
}

// Static.
GURL SyncStoppedReporter::GetSyncEventURL(const GURL& sync_service_url) {
  std::string path = sync_service_url.path();
  if (path.empty() || *path.rbegin() != '/') {
    path += '/';
  }
  path += kEventEndpoint;
  GURL::Replacements replacements;
  replacements.SetPathStr(path);
  return sync_service_url.ReplaceComponents(replacements);
}

}  // namespace syncer