File: cbcm_invalidations_initializer.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 (156 lines) | stat: -rw-r--r-- 6,153 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
// Copyright 2021 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/policy/cbcm_invalidations_initializer.h"

#include "base/memory/raw_ptr.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/device_identity/device_oauth2_token_service.h"
#include "chrome/browser/device_identity/device_oauth2_token_service_factory.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/policy/device_account_initializer.h"
#include "google_apis/gaia/gaia_constants.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"

namespace policy {

// A helper class to make the appropriate calls into the device account
// initializer and manage the ChromeBrowserCloudManagementRegistrar callback's
// lifetime.
class CBCMInvalidationsInitializer::MachineLevelDeviceAccountInitializerHelper
    : public DeviceAccountInitializer::Delegate {
 public:
  using Callback = base::OnceCallback<void(bool)>;

  // |policy_client| should be registered and outlive this object.
  MachineLevelDeviceAccountInitializerHelper(
      const std::string& service_account_email,
      policy::CloudPolicyClient* policy_client,
      Callback callback,
      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
      : service_account_email_(service_account_email),
        policy_client_(policy_client),
        callback_(std::move(callback)),
        url_loader_factory_(url_loader_factory) {
    DCHECK(url_loader_factory_);

    device_account_initializer_ =
        std::make_unique<DeviceAccountInitializer>(policy_client_, this);
    device_account_initializer_->FetchToken();
  }

  MachineLevelDeviceAccountInitializerHelper& operator=(
      MachineLevelDeviceAccountInitializerHelper&) = delete;
  MachineLevelDeviceAccountInitializerHelper(
      MachineLevelDeviceAccountInitializerHelper&) = delete;
  MachineLevelDeviceAccountInitializerHelper(
      MachineLevelDeviceAccountInitializerHelper&&) = delete;

  ~MachineLevelDeviceAccountInitializerHelper() override = default;

  // DeviceAccountInitializer::Delegate:
  void OnDeviceAccountTokenFetched(bool empty_token) override {
    if (empty_token) {
      // Not being able to obtain a token isn't a showstopper for machine
      // level policies: the browser will fallback to fetching policies on a
      // regular schedule and won't support remote commands. Getting a refresh
      // token will be reattempted on the next successful policy fetch.
      std::move(callback_).Run(false);
      return;
    }

    device_account_initializer_->StoreToken();
  }

  void OnDeviceAccountTokenStored() override {
    // When the token is stored, the account init procedure is complete and
    // it's now time to save the associated email address.
    DeviceOAuth2TokenServiceFactory::Get()->SetServiceAccountEmail(
        service_account_email_);
    std::move(callback_).Run(true);
  }

  void OnDeviceAccountTokenFetchError(
      std::optional<DeviceManagementStatus> /*dm_status*/) override {
    std::move(callback_).Run(false);
  }

  void OnDeviceAccountTokenStoreError() override {
    std::move(callback_).Run(false);
  }

  void OnDeviceAccountClientError(DeviceManagementStatus status) override {
    std::move(callback_).Run(false);
  }

  enterprise_management::DeviceServiceApiAccessRequest::DeviceType
  GetRobotAuthCodeDeviceType() override {
    return enterprise_management::DeviceServiceApiAccessRequest::CHROME_BROWSER;
  }

  std::set<std::string> GetRobotOAuthScopes() override {
    return {
        GaiaConstants::kGoogleUserInfoEmail,
        GaiaConstants::kFCMOAuthScope,
    };
  }

  scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
      override {
    return url_loader_factory_;
  }

  std::string service_account_email_;
  raw_ptr<policy::CloudPolicyClient> policy_client_;
  std::unique_ptr<DeviceAccountInitializer> device_account_initializer_;
  Callback callback_;
  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
};

CBCMInvalidationsInitializer::CBCMInvalidationsInitializer(Delegate* delegate)
    : delegate_(delegate) {}

CBCMInvalidationsInitializer::~CBCMInvalidationsInitializer() = default;

void CBCMInvalidationsInitializer::OnServiceAccountSet(
    CloudPolicyClient* client,
    const std::string& account_email) {
  // If there's no invalidations service active yet, now's the time to start it.
  // It will be notified when the service account for is ready to be used.
  if (!delegate_->IsInvalidationsServiceStarted())
    delegate_->StartInvalidations();

  // If there's no refresh token when a policy has a service account, or the
  // service account in the policy doesn't match the one in the token service,
  // the service account has to be initialized to the one in the policy.
  if (!DeviceOAuth2TokenServiceFactory::Get()->RefreshTokenIsAvailable() ||
      DeviceOAuth2TokenServiceFactory::Get()->GetRobotAccountId() !=
          CoreAccountId::FromRobotEmail(account_email)) {
    // Initialize the device service account and fetch auth codes to exchange
    // for a refresh token. Creating this object starts that process and the
    // callback will be called from it whether it succeeds or not.
    account_initializer_helper_ =
        std::make_unique<MachineLevelDeviceAccountInitializerHelper>(
            account_email, client,
            base::BindOnce(&CBCMInvalidationsInitializer::AccountInitCallback,
                           base::Unretained(this), account_email),
            delegate_->GetURLLoaderFactory()
                ? delegate_->GetURLLoaderFactory()
                : g_browser_process->system_network_context_manager()
                      ->GetSharedURLLoaderFactory());
  }
}

void CBCMInvalidationsInitializer::AccountInitCallback(
    const std::string& account_email,
    bool success) {
  account_initializer_helper_.reset();
  if (!success) {
    DVLOG(1)
        << "There was an error initializing the service account with email: "
        << account_email;
  }
}

}  // namespace policy