File: bruschetta_util.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 (246 lines) | stat: -rw-r--r-- 8,888 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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// Copyright 2022 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/bruschetta/bruschetta_util.h"

#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ash/bruschetta/bruschetta_pref_names.h"
#include "chrome/browser/ash/bruschetta/bruschetta_service.h"
#include "chrome/browser/ash/bruschetta/bruschetta_service_factory.h"
#include "chrome/browser/ash/guest_os/guest_id.h"
#include "chrome/browser/ash/guest_os/guest_os_pref_names.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/ash/experiences/guest_os/virtual_machines/virtual_machines_util.h"
#include "components/prefs/pref_service.h"
#include "ui/base/l10n/l10n_util.h"

namespace bruschetta {

namespace {
std::optional<const base::Value::Dict*> GetConfigWithEnabledLevel(
    const Profile* profile,
    const std::string& config_id,
    prefs::PolicyEnabledState enabled_level) {
  // If virtual machines are disabled, we should treat every policy as
  // BLOCKED. If the caller is looking for an enabled level of RUN_ALLOWED
  // or higher we should return nothing, but it can still be useful in
  // some places to retrieve a config even if it's currently BLOCKED e.g. for
  // display names.
  if (!virtual_machines::AreVirtualMachinesAllowedByPolicy() &&
      enabled_level > prefs::PolicyEnabledState::BLOCKED) {
    return std::nullopt;
  }

  const auto* config_ptr = profile->GetPrefs()
                               ->GetDict(prefs::kBruschettaVMConfiguration)
                               .FindDict(config_id);
  if (!config_ptr || config_ptr->FindInt(prefs::kPolicyEnabledKey) <
                         static_cast<int>(enabled_level)) {
    return std::nullopt;
  }

  return config_ptr;
}
}  // namespace

const char kToolsDlc[] = "termina-tools-dlc";
const char kUefiDlc[] = "edk2-ovmf-dlc";

const char kBruschettaVmName[] = "bru";

const std::string BruschettaResultString(const BruschettaResult res) {
  switch (res) {
    case BruschettaResult::kUnknown:
      return l10n_util::GetStringUTF8(IDS_BRUSCHETTA_RESULT_UNKNOWN);
    case BruschettaResult::kSuccess:
      return l10n_util::GetStringUTF8(IDS_BRUSCHETTA_RESULT_SUCCESS);
    case BruschettaResult::kDlcInstallError:
      return l10n_util::GetStringUTF8(IDS_BRUSCHETTA_RESULT_DLC_INSTALL_ERROR);
    case BruschettaResult::kStartVmFailed:
      return l10n_util::GetStringUTF8(IDS_BRUSCHETTA_RESULT_START_VM_FAILED);
    case BruschettaResult::kTimeout:
      return l10n_util::GetStringUTF8(IDS_BRUSCHETTA_RESULT_TIMEOUT);
    case BruschettaResult::kForbiddenByPolicy:
      return l10n_util::GetStringUTF8(
          IDS_BRUSCHETTA_RESULT_FORBIDDEN_BY_POLICY);
    case BruschettaResult::kConciergeUnavailable:
      return l10n_util::GetStringUTF8(
          IDS_BRUSCHETTA_RESULT_CONCIERGE_UNAVAILABLE);
  }
  return "unknown code";
}

guest_os::GuestId GetBruschettaAlphaId() {
  return MakeBruschettaId(kBruschettaVmName);
}

guest_os::GuestId MakeBruschettaId(std::string vm_name) {
  return guest_os::GuestId{guest_os::VmType::BRUSCHETTA, std::move(vm_name),
                           "penguin"};
}

std::optional<const base::Value::Dict*> GetRunnableConfig(
    const Profile* profile,
    const std::string& config_id) {
  return GetConfigWithEnabledLevel(profile, config_id,
                                   prefs::PolicyEnabledState::RUN_ALLOWED);
}

base::FilePath BruschettaChromeOSBaseDirectory() {
  return base::FilePath("/mnt/shared");
}

std::optional<const base::Value::Dict*> GetInstallableConfig(
    const Profile* profile,
    const std::string& config_id) {
  return GetConfigWithEnabledLevel(profile, config_id,
                                   prefs::PolicyEnabledState::INSTALL_ALLOWED);
}

bool HasInstallableConfig(const Profile* profile,
                          const std::string& config_id) {
  return GetInstallableConfig(profile, config_id).has_value();
}

base::flat_map<std::string, base::Value::Dict> GetInstallableConfigs(
    const Profile* profile) {
  base::flat_map<std::string, base::Value::Dict> ret;
  for (auto it :
       profile->GetPrefs()->GetDict(prefs::kBruschettaVMConfiguration)) {
    if (HasInstallableConfig(profile, it.first)) {
      ret.emplace(it.first, it.second.GetDict().Clone());
    }
  }

  return ret;
}

void SortInstallableConfigs(std::vector<InstallableConfig>* configs) {
  auto GetDisplayOrder = [](const InstallableConfig& c) -> int {
    return c.second.FindInt(bruschetta::prefs::kPolicyDisplayOrderKey)
        .value_or(0);
  };
  std::sort(configs->begin(), configs->end(),
            [&GetDisplayOrder](const InstallableConfig& a,
                               const InstallableConfig& b) {
              return GetDisplayOrder(a) < GetDisplayOrder(b);
            });
}

bool IsInstalled(Profile* profile, const guest_os::GuestId& guest_id) {
  const base::Value* value = guest_os::GetContainerPrefValue(
      profile, guest_id, guest_os::prefs::kVmNameKey);
  return value != nullptr;
}

std::optional<RunningVmPolicy> GetLaunchPolicyForConfig(Profile* profile,
                                                        std::string config_id) {
  auto config_option = GetRunnableConfig(profile, config_id);
  if (!config_option.has_value()) {
    return std::nullopt;
  }
  const auto* config = *config_option;

  RunningVmPolicy ret = {.vtpm_enabled =
                             config->FindDict(prefs::kPolicyVTPMKey)
                                 ->FindBool(prefs::kPolicyVTPMEnabledKey)
                                 .value()};

  return ret;
}

std::string GetVmUsername(const Profile* profile) {
  std::string username = profile->GetProfileUserName();
  // Return the part before the '@' if this is an email. Since find returns
  // std::string::npos if it can't find the token this will return the full
  // username in that case.
  return username.substr(0, username.find("@"));
}

std::optional<const base::Value::Dict*> GetConfigForGuest(
    Profile* profile,
    const guest_os::GuestId& guest_id,
    prefs::PolicyEnabledState enabled_level) {
  const auto* config_id_val = guest_os::GetContainerPrefValue(
      profile, guest_id, guest_os::prefs::kBruschettaConfigId);
  if (!config_id_val) {
    return std::nullopt;
  }

  const auto& config_id = config_id_val->GetString();

  return GetConfigWithEnabledLevel(profile, config_id, enabled_level);
}

std::u16string GetOverallVmName(Profile* profile) {
  const std::u16string fallback_name =
      l10n_util::GetStringUTF16(IDS_BRUSCHETTA_NAME);
  if (!profile) {
    // If no profile is present (e.g. some tests), we can't access the policy.
    return fallback_name;
  }

  // First see if the name is explicitly set in policy.
  const auto& installer_config =
      profile->GetPrefs()->GetDict(prefs::kBruschettaInstallerConfiguration);
  const auto* display_name =
      installer_config.FindString(prefs::kPolicyDisplayNameKey);
  if (display_name) {
    return base::UTF8ToUTF16(*display_name);
  }

  // If not, pick the name of the first VM in configuration.
  std::vector<bruschetta::InstallableConfig> configs =
      bruschetta::GetInstallableConfigs(profile).extract();
  if (!configs.empty()) {
    SortInstallableConfigs(&configs);
    const base::Value::Dict& first_vm = configs[0].second;
    const auto* name = first_vm.FindString(prefs::kPolicyNameKey);
    if (name) {
      return base::UTF8ToUTF16(*name);
    }
    // Config exists but no name, use the key as its name.
    return base::UTF8ToUTF16(configs[0].first);
  }
  return fallback_name;
}

GURL GetLearnMoreUrl(Profile* profile) {
  // First see if the name is explicitly set in policy.
  const auto& installer_config =
      profile->GetPrefs()->GetDict(prefs::kBruschettaInstallerConfiguration);
  const auto* url = installer_config.FindString(prefs::kPolicyLearnMoreUrlKey);
  if (url) {
    return GURL(*url);
  }
  return GURL();
}

std::string GetDisplayName(Profile* profile, guest_os::GuestId guest) {
  auto config =
      GetConfigForGuest(profile, guest, prefs::PolicyEnabledState::BLOCKED);
  const std::string* name = nullptr;
  if (config.has_value()) {
    name = config.value()->FindString(prefs::kPolicyNameKey);
  }
  if (name) {
    return *name;
  }
  // If the config doesn't exist, the terminal will default to
  // <vm_name>:<container_name>, but container_name isn't meaningful for us
  // so just use the vm_name instead.
  return guest.vm_name;
}

bool IsBruschettaRunning(Profile* profile) {
  auto* service = bruschetta::BruschettaServiceFactory::GetForProfile(profile);
  return service && service->IsVmRunning(kBruschettaVmName);
}

std::string GetBruschettaDisplayName(Profile* profile) {
  return GetDisplayName(profile, GetBruschettaAlphaId());
}

}  // namespace bruschetta