File: app_capability_access_cache.cc

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • 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 (135 lines) | stat: -rw-r--r-- 4,192 bytes parent folder | download | duplicates (9)
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
// 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 "components/services/app_service/public/cpp/app_capability_access_cache.h"

#include <utility>
#include "base/observer_list.h"

namespace apps {

AppCapabilityAccessCache::Observer::~Observer() {
  CHECK(!IsInObserverList());
}

AppCapabilityAccessCache::AppCapabilityAccessCache()
    : account_id_(EmptyAccountId()) {}

AppCapabilityAccessCache::~AppCapabilityAccessCache() {
  for (auto& obs : observers_) {
    obs.OnAppCapabilityAccessCacheWillBeDestroyed(this);
  }
  DCHECK(observers_.empty());
}

void AppCapabilityAccessCache::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void AppCapabilityAccessCache::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

void AppCapabilityAccessCache::SetAccountId(const AccountId& account_id) {
  account_id_ = account_id;
}

std::set<std::string> AppCapabilityAccessCache::GetAppsAccessingCamera() {
  std::set<std::string> app_ids;
  ForEachApp([&app_ids](const apps::CapabilityAccessUpdate& update) {
    auto camera = update.Camera();
    if (camera.value_or(false)) {
      app_ids.insert(update.AppId());
    }
  });
  return app_ids;
}

std::set<std::string> AppCapabilityAccessCache::GetAppsAccessingMicrophone() {
  std::set<std::string> app_ids;
  ForEachApp([&app_ids](const apps::CapabilityAccessUpdate& update) {
    auto microphone = update.Microphone();
    if (microphone.value_or(false)) {
      app_ids.insert(update.AppId());
    }
  });
  return app_ids;
}

std::set<std::string> AppCapabilityAccessCache::GetAppsAccessingCapabilities() {
  std::set<std::string> app_ids;
  ForEachApp([&app_ids](const apps::CapabilityAccessUpdate& update) {
    if (update.IsAccessingAnyCapability()) {
      app_ids.insert(update.AppId());
    }
  });
  return app_ids;
}

void AppCapabilityAccessCache::OnCapabilityAccesses(
    std::vector<CapabilityAccessPtr> deltas) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);

  if (!deltas_in_progress_.empty()) {
    std::move(deltas.begin(), deltas.end(),
              std::back_inserter(deltas_pending_));
    return;
  }

  DoOnCapabilityAccesses(std::move(deltas));
  while (!deltas_pending_.empty()) {
    std::vector<CapabilityAccessPtr> pending;
    pending.swap(deltas_pending_);
    DoOnCapabilityAccesses(std::move(pending));
  }
}

void AppCapabilityAccessCache::DoOnCapabilityAccesses(
    std::vector<CapabilityAccessPtr> deltas) {
  // Merge any deltas elements that have the same app_id. If an observer's
  // OnCapabilityAccessUpdate calls back into this AppCapabilityAccessCache then
  // we can therefore present a single delta for any given app_id.
  for (auto& delta : deltas) {
    auto d_iter = deltas_in_progress_.find(delta->app_id);
    if (d_iter != deltas_in_progress_.end()) {
      CapabilityAccessUpdate::Merge(d_iter->second, delta.get());
    } else {
      deltas_in_progress_[delta->app_id] = delta.get();
    }
  }

  // The remaining for loops range over the deltas_in_progress_ map, not the
  // deltas vector, so that OnCapabilityAccessUpdate is called only once per
  // unique app_id.

  // Notify the observers for every de-duplicated delta.
  for (const auto& d_iter : deltas_in_progress_) {
    auto s_iter = states_.find(d_iter.first);
    CapabilityAccess* state =
        (s_iter != states_.end()) ? s_iter->second.get() : nullptr;
    CapabilityAccess* delta = d_iter.second;

    for (auto& obs : observers_) {
      obs.OnCapabilityAccessUpdate(
          CapabilityAccessUpdate(state, delta, account_id_));
    }
  }

  // Update the states for every de-duplicated delta.
  for (const auto& d_iter : deltas_in_progress_) {
    auto s_iter = states_.find(d_iter.first);
    CapabilityAccess* state =
        (s_iter != states_.end()) ? s_iter->second.get() : nullptr;
    CapabilityAccess* delta = d_iter.second;

    if (state) {
      CapabilityAccessUpdate::Merge(state, delta);
    } else {
      states_.insert(std::make_pair(delta->app_id, delta->Clone()));
    }
  }
  deltas_in_progress_.clear();
}

}  // namespace apps