File: send_message_express.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 (157 lines) | stat: -rw-r--r-- 6,468 bytes parent folder | download | duplicates (6)
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
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/nearby_sharing/instantmessaging/send_message_express.h"

#include <optional>
#include <sstream>

#include "base/metrics/histogram_functions.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/nearby_sharing/instantmessaging/constants.h"
#include "chrome/browser/nearby_sharing/instantmessaging/proto/instantmessaging.pb.h"
#include "chrome/browser/nearby_sharing/instantmessaging/token_fetcher.h"
#include "chromeos/ash/components/nearby/common/client/nearby_http_result.h"
#include "components/cross_device/logging/logging.h"
#include "net/base/load_flags.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 "url/gurl.h"

namespace {

// 256 KB as max response size.
constexpr int kMaxSendResponseSize = 256;

// Timeout for network calls to instantmessaging servers.
const base::TimeDelta kNetworkTimeout = base::Milliseconds(2500);

const net::NetworkTrafficAnnotationTag kTrafficAnnotation =
    net::DefineNetworkTrafficAnnotation("send_message_express", R"(
        semantics {
          sender: "SendMessageExpress"
          description:
            "Sends a message to another device via a Gaia authenticated Google"
            " messaging backend."
          trigger:
            "User uses any Chrome cross-device sharing feature and selects a"
            " peer device to send the data to."
          data: "WebRTC session description protocol messages are exchanged "
            "between devices to set up a peer to peer connection as documented "
            "in https://tools.ietf.org/html/rfc4566 and "
            "https://www.w3.org/TR/webrtc/#session-description-model. No user "
            "data is sent in the request."
          destination: GOOGLE_OWNED_SERVICE
          }
          policy {
            cookies_allowed: NO
            setting:
              "This feature is only enabled for signed-in users who enable "
              "Nearby sharing or Phone Hub."
            chrome_policy {
              NearbyShareAllowed {
                policy_options {mode: MANDATORY}
                NearbyShareAllowed: false
              },
              PhoneHubAllowed {
                policy_options {mode: MANDATORY}
                PhoneHubAllowed: false
              }
            }
          })");

void LogSendResult(bool success,
                   const ash::nearby::NearbyHttpStatus& http_status,
                   const std::string& request_id) {
  std::stringstream ss;
  ss << "Instant messaging send express " << (success ? "succeeded" : "failed")
     << " for request " << request_id << ". HTTP status: " << http_status;
  if (success) {
    CD_LOG(VERBOSE, Feature::NS) << ss.str();
  } else {
    CD_LOG(ERROR, Feature::NS) << ss.str();
  }
  base::UmaHistogramBoolean(
      "Nearby.Connections.InstantMessaging.SendExpress.Result", success);
  if (!success) {
    base::UmaHistogramSparse(
        "Nearby.Connections.InstantMessaging.SendExpress.Result.FailureReason",
        http_status.GetResultCodeForMetrics());
  }
}

}  // namespace

SendMessageExpress::SendMessageExpress(
    signin::IdentityManager* identity_manager,
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
    : token_fetcher_(identity_manager),
      url_loader_factory_(std::move(url_loader_factory)) {}

SendMessageExpress::~SendMessageExpress() = default;

void SendMessageExpress::SendMessage(
    const chrome_browser_nearby_sharing_instantmessaging::
        SendMessageExpressRequest& request,
    SuccessCallback callback) {
  token_fetcher_.GetAccessToken(base::BindOnce(
      &SendMessageExpress::DoSendMessage, weak_ptr_factory_.GetWeakPtr(),
      request, std::move(callback)));
}

void SendMessageExpress::DoSendMessage(
    const chrome_browser_nearby_sharing_instantmessaging::
        SendMessageExpressRequest& request,
    SuccessCallback callback,
    const std::string& oauth_token) {
  base::UmaHistogramBoolean(
      "Nearby.Connections.InstantMessaging.SendExpress.OAuthTokenFetchResult",
      !oauth_token.empty());
  if (oauth_token.empty()) {
    CD_LOG(ERROR, Feature::NS) << __func__ << ": Failed to fetch OAuth token.";
    std::move(callback).Run(false);
    // NOTE: |this| might be destroyed here after running the callback
    return;
  }

  std::string request_id = request.header().request_id();

  auto resource_request = std::make_unique<network::ResourceRequest>();
  resource_request->url = GURL(kInstantMessagingSendMessageAPI);
  resource_request->load_flags =
      net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE;
  resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
  resource_request->method = net::HttpRequestHeaders::kPostMethod;
  resource_request->headers.AddHeaderFromString(
      base::StringPrintf(kAuthorizationHeaderFormat, oauth_token.c_str()));

  std::unique_ptr<network::SimpleURLLoader> send_url_loader =
      network::SimpleURLLoader::Create(std::move(resource_request),
                                       kTrafficAnnotation);
  auto* const send_url_loader_ptr = send_url_loader.get();
  send_url_loader->SetTimeoutDuration(kNetworkTimeout);
  send_url_loader->AttachStringForUpload(request.SerializeAsString(),
                                         "application/x-protobuf");
  send_url_loader_ptr->DownloadToString(
      url_loader_factory_.get(),
      base::BindOnce(&SendMessageExpress::OnSendMessageResponse,
                     weak_ptr_factory_.GetWeakPtr(), request_id,
                     std::move(send_url_loader), std::move(callback)),
      kMaxSendResponseSize);
}

void SendMessageExpress::OnSendMessageResponse(
    const std::string& request_id,
    std::unique_ptr<network::SimpleURLLoader> url_loader,
    SuccessCallback callback,
    std::unique_ptr<std::string> response_body) {
  ash::nearby::NearbyHttpStatus http_status(url_loader->NetError(),
                                            url_loader->ResponseInfo());
  bool success =
      http_status.IsSuccess() && response_body && !response_body->empty();
  LogSendResult(success, http_status, request_id);
  std::move(callback).Run(success);
  // NOTE: |this| might be destroyed here after running the callback
}