blob: 1b88cd25359db635fb44efe89ae7fd21347412e8 [file]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/usage_stats_consent.h"
#include <memory>
#include <optional>
#include <string>
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_file_value_serializer.h"
#include "base/logging.h"
#include "base/notimplemented.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "remoting/base/branding.h"
#include "remoting/base/file_path_util_linux.h"
#include "remoting/base/is_google_email.h"
#include "remoting/host/config_file_watcher.h"
#include "remoting/host/host_config.h"
namespace remoting {
namespace {
inline base::FilePath GetMultiProcessHostUsageStatsConsentFile() {
return GetMultiProcessHostGlobalConfigDir().Append(
kDefaultUnprivilegedConfigFileName);
}
bool GetUsageStatsConsentFromFile(const base::FilePath& path,
bool* allowed,
bool* set_by_policy) {
*set_by_policy = false;
*allowed = false;
JSONFileValueDeserializer deserializer(path);
int error_code;
std::string error_message;
std::unique_ptr<base::Value> value =
deserializer.Deserialize(&error_code, &error_message);
if (!value) {
LOG(ERROR) << "Failed to read usage stats consent from file: "
<< error_message << " (error code: " << error_code << ")";
return false;
}
if (!value->is_dict()) {
LOG(ERROR) << "Usage stats consent file does not contain a dictionary.";
return false;
}
const base::DictValue& dict = value->GetDict();
auto usage_stats_consent = dict.FindBool(kUsageStatsConsentConfigPath);
if (usage_stats_consent.has_value()) {
*allowed = *usage_stats_consent;
return true;
}
// Note: kHostOwnerConfigPath only exists in the per-user host config file.
const std::string* host_owner_ptr = dict.FindString(kHostOwnerConfigPath);
if (host_owner_ptr) {
// Opt into crash reporting for Googlers if not set in the config.
*allowed = IsGoogleEmail(*host_owner_ptr);
return true;
}
return false;
}
} // namespace
bool GetUsageStatsConsent(bool* allowed, bool* set_by_policy) {
std::string consent_content;
// We don't know if the host is single-process or multi-process, so we always
// check the consent file first.
if (base::PathExists(GetMultiProcessHostUsageStatsConsentFile())) {
return GetUsageStatsConsentFromFile(
GetMultiProcessHostUsageStatsConsentFile(), allowed, set_by_policy);
}
std::string filename = GetHostHash() + ".json";
base::FilePath config_path = GetConfigDir().Append(filename);
if (!base::PathExists(config_path)) {
LOG(ERROR) << "Cannot find usage stats consent file: " << config_path;
return false;
}
return GetUsageStatsConsentFromFile(config_path, allowed, set_by_policy);
}
bool IsUsageStatsAllowed() {
bool allowed;
bool set_by_policy;
return GetUsageStatsConsent(&allowed, &set_by_policy) && allowed;
}
bool SetUsageStatsConsent(bool allowed) {
NOTIMPLEMENTED();
return false;
}
} // namespace remoting