blob: 785875833585c4a5aa1b8008d6f39f217a75dca1 [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 <sysexits.h>
#include <base/command_line.h>
#include <base/logging.h>
#include <base/posix/eintr_wrapper.h>
#include <base/strings/string_util.h>
#include <brillo/flag_helper.h>
#include <brillo/process/process.h>
#include "policy_utils/policy_tool.h"
namespace {
// Help message to show when the --help command line switch is specified.
constexpr char kHelpMessage[] =
"Device Policy tool\n"
"Set or clear device policies on the local device. Setting a local\n"
"policy overrides the policy set in Chrome. The command format is:\n"
" policy [set|clear] PolicyName [value]\n"
"The tool will try to automatically detect whether Google Chrome or\n"
"Chromium is used. If that fails, you can use the options to force one\n"
"or the other.\n"
" policy set ShowHomeButton true\n"
" policy clear ShowHomeButton\n\n"
"Policy names are not case sensitive.";
constexpr char kUsageMessage[] =
" policy [set|clear] PolicyName [value]\n"
" policy --help for more detailed help\n";
constexpr char kPolicyListHeader[] =
"List of available policies:\n";
// Path to chrome executable in linux.
constexpr char kChromePath[] = "/opt/google/chrome/chrome";
// Return a PolicyTool singleton.
const policy_utils::PolicyTool& GetPolicyTool(bool for_chromium = false) {
static policy_utils::PolicyTool policy_tool(
for_chromium ? policy_utils::PolicyTool::kChromiumPolicyDirPath
: policy_utils::PolicyTool::kChromePolicyDirPath);
return policy_tool;
// Show a list of all policies this tool can edit.
void ListPolicies() {
const policy_utils::PolicyTool::PolicyList& policies =
std::string name_list;
for (auto& policy : policies) {
name_list += " " + policy + "\n";
LOG(INFO) << kPolicyListHeader << name_list;
// Run |process| and capture its stdout output to |output|.
int RunAndCaptureOutput(brillo::ProcessImpl* process, std::string* output) {
constexpr size_t kBufferSize = 4096;
process->RedirectUsingPipe(STDOUT_FILENO, false);
if (process->Start()) {
const int out = process->GetPipe(STDOUT_FILENO);
char buffer[kBufferSize];
while (true) {
const ssize_t count = HANDLE_EINTR(read(out, buffer, kBufferSize));
if (count < 0) {
if (count == 0)
return process->Wait();
output->append(buffer, count);
return -1;
// Query the chrome version string by running the chrome executable.
// Return whether successful.
bool GetChromeVersion(std::string* version) {
brillo::ProcessImpl chrome;
int exit_code = RunAndCaptureOutput(&chrome, version);
return (exit_code == EX_OK && !version->empty());
} // namespace
int main(int argc, char** argv) {
DEFINE_bool(list, false,
"Show the list of policies this tool can set or clear");
DEFINE_bool(chromium, false, "Force setting policies for Chromium");
DEFINE_bool(chrome, false, "Force setting policies for Google Chrome");
brillo::FlagHelper::Init(argc, argv, kHelpMessage);
base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
if (FLAGS_list) {
return 0;
const base::CommandLine::StringVector& args = cl->GetArgs();
if (args.size() < 2) {
LOG(INFO) << kUsageMessage;
return 1;
// Determine whether we should set the policies for Google Chrome or Chromium,
// either from cmd-line options or automatically.
bool set_policies_for_chromium = false;
if (FLAGS_chromium) {
set_policies_for_chromium = true;
} else if (FLAGS_chrome) {
set_policies_for_chromium = false;
} else {
std::string chrome_version;
if (!GetChromeVersion(&chrome_version)) {
LOG(ERROR) << "Unable to get Chrome version.\n"
"You can use cmd-line options '--chrome' or '--chromium'\n"
"to force either Google Chrome or Chromium";
return 1;
set_policies_for_chromium = base::StartsWith(
chrome_version, "Chromium", base::CompareCase::INSENSITIVE_ASCII);
if (!GetPolicyTool(set_policies_for_chromium).DoCommand(args)) {
LOG(INFO) << "Failed";
return 1;
LOG(INFO) << "Done";
return 0;