blob: 42193f7e85d4df8c4c11f789ac42b507762e84f7 [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "policy_utils/policy_tool.h"
#include <base/check_op.h>
#include <base/logging.h>
#include <base/strings/string_util.h>
#include <base/values.h>
namespace {
using base::CommandLine;
using base::CompareCaseInsensitiveASCII;
using base::Value;
using policy_utils::PolicyWriter;
// The command that is being executed.
enum class Command { CMD_CLEAR, CMD_SET, CMD_UNKNOWN };
// Individual policies that this tool can handle.
constexpr char kPolicyDeviceAllowBluetooth[] = "DeviceAllowBlueTooth";
constexpr char kShowHomeButton[] = "ShowHomeButton";
constexpr char kBookmarkBarEnabled[] = "BookmarkBarEnabled";
// The same policies, bundled up in a list.
const policy_utils::PolicyTool::PolicyList known_policies = {
kBookmarkBarEnabled, kPolicyDeviceAllowBluetooth, kShowHomeButton};
// Compare two strings for equality ignoring case.
bool IsEqualNoCase(const std::string& a, const std::string& b) {
return CompareCaseInsensitiveASCII(a, b) == 0;
// Returns whether the policy, identified by its name, is supported.
bool VerifyPolicyName(const std::string& policy_name) {
for (const std::string& policy : known_policies) {
if (IsEqualNoCase(policy, policy_name))
return true;
return false;
// Parse and return the command from the cmd-line arguments. Returns
// Command::CMD_UNKNOWN if the command string is missing or not recognized.
Command GetCommandFromArgs(const CommandLine::StringVector& args) {
if (args.size() < 1)
return Command::CMD_UNKNOWN;
const std::string& cmd = args[0];
if (IsEqualNoCase(cmd, "set"))
return Command::CMD_SET;
else if (IsEqualNoCase(cmd, "clear"))
return Command::CMD_CLEAR;
LOG(ERROR) << "Not a valid command: " << cmd;
return Command::CMD_UNKNOWN;
// Parse and return a boolean value from the cmd-line arguments. Returns a null
// Value if the cmd-line value argument is missing or not a boolean.
Value GetBoolValueFromArgs(const CommandLine::StringVector& args) {
if (args.size() >= 3) {
const std::string& value = args[2];
if (IsEqualNoCase(value, "true"))
return Value(true);
else if (IsEqualNoCase(value, "false"))
return Value(false);
LOG(ERROR) << "Not a valid boolean value: " << value;
return Value();
return Value();
// Parse and return the value that is being set for the given policy. Returns
// a null Value if the set-value is missing or is not not the right type for
// the given policy.
Value GetValueForSetCommand(const std::string& policy,
const CommandLine::StringVector& args) {
if (IsEqualNoCase(policy, kPolicyDeviceAllowBluetooth) ||
IsEqualNoCase(policy, kShowHomeButton) ||
IsEqualNoCase(policy, kBookmarkBarEnabled)) {
return GetBoolValueFromArgs(args);
return Value();
// Handle command |cmd| for the given policy, taking any required value from
// the args list. Returns 0 in case of success or an error code otherwise.
bool HandleCommandForPolicy(Command cmd,
const std::string& policy,
const CommandLine::StringVector& args,
const PolicyWriter& writer) {
if (!VerifyPolicyName(policy)) {
LOG(ERROR) << "Not a valid policy name: " << policy;
return false;
// If this is a 'set' command, parse the value to set from the args.
Value set_value;
if (cmd == Command::CMD_SET) {
set_value = GetValueForSetCommand(policy, args);
if (set_value.type() == Value::Type::NONE) {
LOG(ERROR) << "No value or invalid value specified";
return false;
bool result = false;
if (IsEqualNoCase(policy, kPolicyDeviceAllowBluetooth)) {
if (cmd == Command::CMD_SET)
result = writer.SetDeviceAllowBluetooth(set_value.GetBool());
result = writer.ClearDeviceAllowBluetooth();
} else if (IsEqualNoCase(policy, kShowHomeButton)) {
if (cmd == Command::CMD_SET)
result = writer.SetShowHomeButton(set_value.GetBool());
result = writer.ClearShowHomeButton();
} else if (IsEqualNoCase(policy, kBookmarkBarEnabled)) {
if (cmd == Command::CMD_SET)
result = writer.SetBookmarkBarEnabled(set_value.GetBool());
result = writer.ClearBookmarkBarEnabled();
if (!result) {
LOG(ERROR) << "Could not write policy to file.\n"
"You may need to run policy with sudo. "
"You may also need to make your rootfs writeable.";
return result;
} // namespace
namespace policy_utils {
using base::CommandLine;
constexpr char PolicyTool::kChromePolicyDirPath[];
constexpr char PolicyTool::kChromiumPolicyDirPath[];
// PolicyTool::PolicyTool() : writer_(kChromePolicyDirPath) {}
PolicyTool::PolicyTool(const std::string& policy_dir_path)
: writer_(policy_dir_path) {}
bool PolicyTool::DoCommand(const CommandLine::StringVector& args) const {
// Args must have at least one command and one policy name.
if (args.size() < 2)
return false;
Command cmd = GetCommandFromArgs(args);
if (cmd == Command::CMD_UNKNOWN)
return false;
const std::string& policy = args[1];
return HandleCommandForPolicy(cmd, policy, args, writer_);
const PolicyTool::PolicyList& PolicyTool::get_policies() {
return known_policies;
} // namespace policy_utils