blob: 199636a2b6d7904e33f1227821de7b2a5062fea3 [file] [log] [blame]
// 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 "components/policy/core/common/default_chrome_apps_migrator.h"
#include "components/policy/policy_constants.h"
#include "components/strings/grit/components_strings.h"
namespace policy {
namespace {
std::map<std::string, std::string> GetChromeAppToWebAppMapping() {
return std::map<std::string, std::string>({
{"ejjicmeblgpmajnghnpcppodonldlgfn",
"https://calendar.google.com/calendar/installwebapp?usp=admin"},
{"aohghmighlieiainnegkcijnfilokake",
"https://docs.google.com/document/installwebapp?usp=admin"},
{"apdfllckaahabafndbhieahigkjlhalf",
"https://drive.google.com/drive/installwebapp?usp=admin"},
{"pjkljhegncpnkpknbcohdijeoejaedia",
"https://mail.google.com/mail/installwebapp?usp=admin"},
{"felcaaldnbdncclmgdcncolpebgiejap",
"https://docs.google.com/spreadsheets/installwebapp?usp=admin"},
{"aapocclcgogkmnckokdopfmhonfmgoek",
"https://docs.google.com/presentation/installwebapp?usp=admin"},
{"blpcfgokakmgnkcojhhkbfbldkacnbeo",
"https://www.youtube.com/s/notifications/manifest/cr_install.html"},
{"hmjkmjkepdijhoojdojkdfohbdgmmhki",
"https://keep.google.com/installwebapp?usp=admin"},
});
}
} // namespace
DefaultChromeAppsMigrator::DefaultChromeAppsMigrator()
: DefaultChromeAppsMigrator(GetChromeAppToWebAppMapping()) {}
DefaultChromeAppsMigrator::DefaultChromeAppsMigrator(
std::map<std::string, std::string> chrome_app_to_web_app)
: chrome_app_to_web_app_(std::move(chrome_app_to_web_app)) {}
DefaultChromeAppsMigrator::DefaultChromeAppsMigrator(
DefaultChromeAppsMigrator&&) noexcept = default;
DefaultChromeAppsMigrator& DefaultChromeAppsMigrator::operator=(
DefaultChromeAppsMigrator&&) noexcept = default;
DefaultChromeAppsMigrator::~DefaultChromeAppsMigrator() = default;
void DefaultChromeAppsMigrator::Migrate(PolicyMap* policies) const {
std::vector<std::string> chrome_app_ids =
RemoveChromeAppsFromExtensionForcelist(policies);
// If no Chrome Apps need to be replaced, we have nothing to do.
if (chrome_app_ids.empty())
return;
EnsurePolicyValueIsList(policies, key::kWebAppInstallForceList);
base::Value::List& web_app_policy_value =
policies
->GetMutableValue(key::kWebAppInstallForceList,
base::Value::Type::LIST)
->GetList();
for (const std::string& chrome_app_id : chrome_app_ids) {
base::Value::Dict web_app;
web_app.Set("url", chrome_app_to_web_app_.at(chrome_app_id));
base::Value::List uninstall_list;
uninstall_list.Append(chrome_app_id);
web_app.Set("uninstall_and_replace", std::move(uninstall_list));
web_app_policy_value.Append(std::move(web_app));
}
MigratePinningPolicy(policies);
}
std::vector<std::string>
DefaultChromeAppsMigrator::RemoveChromeAppsFromExtensionForcelist(
PolicyMap* policies) const {
PolicyMap::Entry* forcelist_entry =
policies->GetMutable(key::kExtensionInstallForcelist);
if (!forcelist_entry)
return std::vector<std::string>();
const base::Value* forcelist_value =
forcelist_entry->value(base::Value::Type::LIST);
if (!forcelist_value)
return std::vector<std::string>();
std::vector<std::string> chrome_app_ids;
base::Value::List new_forcelist_value;
for (const auto& list_entry : forcelist_value->GetList()) {
if (!list_entry.is_string()) {
new_forcelist_value.Append(list_entry.Clone());
continue;
}
const std::string entry = list_entry.GetString();
const size_t pos = entry.find(';');
const std::string extension_id = entry.substr(0, pos);
if (chrome_app_to_web_app_.count(extension_id))
chrome_app_ids.push_back(extension_id);
else
new_forcelist_value.Append(entry);
}
forcelist_entry->set_value(base::Value(std::move(new_forcelist_value)));
return chrome_app_ids;
}
void DefaultChromeAppsMigrator::EnsurePolicyValueIsList(
PolicyMap* policies,
const std::string& policy_name) const {
// It is safe to use `GetValueUnsafe()` because type checking is performed
// before the value is used.
const base::Value* policy_value = policies->GetValueUnsafe(policy_name);
if (!policy_value || !policy_value->is_list()) {
const PolicyMap::Entry* forcelist_entry =
policies->Get(key::kExtensionInstallForcelist);
PolicyMap::Entry policy_entry(
forcelist_entry->level, forcelist_entry->scope, forcelist_entry->source,
base::Value(base::Value::Type::LIST), nullptr);
// If `policy_value` has wrong type, add message before overriding value.
if (policy_value) {
policy_entry.AddMessage(PolicyMap::MessageType::kError,
IDS_POLICY_TYPE_ERROR);
}
policies->Set(policy_name, std::move(policy_entry));
}
}
void DefaultChromeAppsMigrator::MigratePinningPolicy(
PolicyMap* policies) const {
base::Value* pinned_apps_value = policies->GetMutableValue(
key::kPinnedLauncherApps, base::Value::Type::LIST);
if (!pinned_apps_value)
return;
for (auto& list_entry : pinned_apps_value->GetList()) {
if (!list_entry.is_string())
continue;
const std::string pinned_app = list_entry.GetString();
auto it = chrome_app_to_web_app_.find(pinned_app);
if (it != chrome_app_to_web_app_.end())
list_entry = base::Value(it->second);
}
}
} // namespace policy