| // 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/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[] = |
| "\n" |
| "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" |
| "\n" |
| " policy [set|clear] PolicyName [value]\n" |
| "\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" |
| "\n" |
| "Examples:\n" |
| " policy set ShowHomeButton true\n" |
| " policy clear ShowHomeButton\n\n" |
| "Policy names are not case sensitive."; |
| |
| constexpr char kUsageMessage[] = |
| "\n" |
| "Usage:\n" |
| " policy [set|clear] PolicyName [value]\n" |
| "or\n" |
| " policy --help for more detailed help\n"; |
| |
| constexpr char kPolicyListHeader[] = |
| "\n" |
| "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 = |
| GetPolicyTool().get_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]; |
| output->clear(); |
| |
| while (true) { |
| const ssize_t count = HANDLE_EINTR(read(out, buffer, kBufferSize)); |
| if (count < 0) { |
| process->Wait(); |
| break; |
| } |
| |
| 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; |
| chrome.AddArg(kChromePath); |
| chrome.AddArg("--version"); |
| |
| 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) { |
| ListPolicies(); |
| 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; |
| } |