File: arc_ui_availability_reporter.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (130 lines) | stat: -rw-r--r-- 4,584 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
// Copyright 2019 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/ash/arc/arc_ui_availability_reporter.h"

#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/ash/arc/arc_optin_uma.h"
#include "chromeos/ash/experiences/arc/session/arc_bridge_service.h"
#include "chromeos/ash/experiences/arc/session/arc_service_manager.h"

namespace arc {

class ArcUiAvailabilityReporter::ConnectionNotifierBase {
 public:
  ConnectionNotifierBase(const ConnectionNotifierBase&) = delete;
  ConnectionNotifierBase& operator=(const ConnectionNotifierBase&) = delete;

  virtual ~ConnectionNotifierBase() = default;

  // Returns true if connection is ready.
  virtual bool IsConnected() = 0;

 protected:
  explicit ConnectionNotifierBase(ArcUiAvailabilityReporter* owner)
      : owner_(owner) {}

  ArcUiAvailabilityReporter* owner() { return owner_; }

 private:
  const raw_ptr<ArcUiAvailabilityReporter> owner_;
};

namespace {

template <typename InstanceType, typename HostType>
class ConnectionNotifier
    : public ArcUiAvailabilityReporter::ConnectionNotifierBase,
      public ConnectionObserver<InstanceType> {
 public:
  // |owner_| owns this object and |ConnectionNotifier| is destroyed in case
  // statistics is reported or ARC session is terminated on user log-out and
  // this automatically destroys this object at time of destroying |owner_|.
  // |holder_| is owned by ArcBridgeService this lives longer than
  // |ArcUiAvailabilityReporter|.
  ConnectionNotifier(ArcUiAvailabilityReporter* owner,
                     ConnectionHolder<InstanceType, HostType>* holder)
      : ArcUiAvailabilityReporter::ConnectionNotifierBase(owner),
        holder_(holder) {
    DCHECK(!holder_->IsConnected());
    holder_->AddObserver(this);
  }

  ConnectionNotifier(const ConnectionNotifier&) = delete;
  ConnectionNotifier& operator=(const ConnectionNotifier&) = delete;

  ~ConnectionNotifier() override { holder_->RemoveObserver(this); }

  // ArcUiAvailabilityReporter::ConnectionNotifierBase:
  bool IsConnected() override { return holder_->IsConnected(); }

  // ConnectionObserver<InstanceType>:
  void OnConnectionReady() override { owner()->MaybeReport(); }

 private:
  const raw_ptr<ConnectionHolder<InstanceType, HostType>> holder_;
};

}  // namespace

ArcUiAvailabilityReporter::ArcUiAvailabilityReporter(Profile* profile,
                                                     Mode mode)
    : profile_(profile), mode_(mode), start_ticks_(base::TimeTicks::Now()) {
  DCHECK(profile);
  // Some unit tests may not have |ArcServiceManager| set.
  ArcServiceManager* const service_manager = ArcServiceManager::Get();
  if (!service_manager)
    return;
  // |initiated_from_oobe| must be set only if |initial_start| is set.
  auto* const arc_bridge = ArcServiceManager::Get()->arc_bridge_service();
  // Not expected instances are connected at the time of creation, however this
  // is not always preserved in tests.
  if (arc_bridge->app()->IsConnected() ||
      arc_bridge->intent_helper()->IsConnected()) {
    LOG(ERROR) << "App and/or intent_helper instances are already connected. "
               << "This is not expected in production.";
    return;
  }

  connection_notifiers_.emplace_back(
      std::make_unique<ConnectionNotifier<mojom::AppInstance, mojom::AppHost>>(
          this, arc_bridge->app()));
  connection_notifiers_.emplace_back(
      std::make_unique<ConnectionNotifier<mojom::IntentHelperInstance,
                                          mojom::IntentHelperHost>>(
          this, arc_bridge->intent_helper()));
}

ArcUiAvailabilityReporter::~ArcUiAvailabilityReporter() = default;

// static
std::string ArcUiAvailabilityReporter::GetHistogramNameForMode(Mode mode) {
  switch (mode) {
    case Mode::kOobeProvisioning:
      return "OobeProvisioning";
    case Mode::kInSessionProvisioning:
      return "InSessionProvisioning";
    case Mode::kAlreadyProvisioned:
      return "AlreadyProvisioned";
  }
}

void ArcUiAvailabilityReporter::MaybeReport() {
  DCHECK(!connection_notifiers_.empty());

  // Check that all tracked instance are connected.
  for (const auto& connection_notifier : connection_notifiers_) {
    if (!connection_notifier->IsConnected())
      return;
  }

  UpdateArcUiAvailableTime(base::TimeTicks::Now() - start_ticks_,
                           GetHistogramNameForMode(mode_), profile_);

  // No more reporting is expected.
  connection_notifiers_.clear();
}

}  // namespace arc