root/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GetSubkeyString
  2. GetValue
  3. GetAction
  4. CheckPolicySettings
  5. ApplyPolicySettings
  6. CreateForUserPolicy
  7. CreateForDevicePolicy
  8. CheckPolicySettings
  9. ApplyPolicySettings
  10. PrepareForDisplaying
  11. pref_path_
  12. SanitizeNetworkConfig
  13. ApplyPolicySettings
  14. ApplyPolicySettings
  15. LoginScreenPowerManagementPolicyHandler
  16. LoginScreenPowerManagementPolicyHandler
  17. ApplyPolicySettings
  18. ApplyPolicySettings
  19. PowerManagementIdleSettingsPolicyHandler
  20. PowerManagementIdleSettingsPolicyHandler
  21. ApplyPolicySettings
  22. ApplyPolicySettings

// Copyright (c) 2012 The Chromium 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 "chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.h"

#include <string>
#include <vector>

#include "ash/magnifier/magnifier_constants.h"
#include "base/callback.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/prefs/pref_value_map.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
#include "chrome/common/pref_names.h"
#include "chromeos/dbus/power_policy_controller.h"
#include "chromeos/network/onc/onc_signature.h"
#include "chromeos/network/onc/onc_utils.h"
#include "chromeos/network/onc/onc_validator.h"
#include "components/onc/onc_constants.h"
#include "components/policy/core/browser/policy_error_map.h"
#include "components/policy/core/common/external_data_fetcher.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/schema.h"
#include "crypto/sha2.h"
#include "grit/component_strings.h"
#include "policy/policy_constants.h"
#include "url/gurl.h"

namespace policy {

namespace {

const char kSubkeyURL[] = "url";
const char kSubkeyHash[] = "hash";

bool GetSubkeyString(const base::DictionaryValue& dict,
                     policy::PolicyErrorMap* errors,
                     const std::string& policy,
                     const std::string& subkey,
                     std::string* value) {
  const base::Value* raw_value = NULL;
  if (!dict.GetWithoutPathExpansion(subkey, &raw_value)) {
    errors->AddError(policy, subkey, IDS_POLICY_NOT_SPECIFIED_ERROR);
    return false;
  }
  std::string string_value;
  if (!raw_value->GetAsString(&string_value)) {
    errors->AddError(policy, subkey, IDS_POLICY_TYPE_ERROR, "string");
    return false;
  }
  if (string_value.empty()) {
    errors->AddError(policy, subkey, IDS_POLICY_NOT_SPECIFIED_ERROR);
    return false;
  }
  *value = string_value;
  return true;
}

const char kScreenDimDelayAC[] = "AC.Delays.ScreenDim";
const char kScreenOffDelayAC[] = "AC.Delays.ScreenOff";
const char kIdleWarningDelayAC[] = "AC.Delays.IdleWarning";
const char kIdleDelayAC[] = "AC.Delays.Idle";
const char kIdleActionAC[] = "AC.IdleAction";

const char kScreenDimDelayBattery[] = "Battery.Delays.ScreenDim";
const char kScreenOffDelayBattery[] = "Battery.Delays.ScreenOff";
const char kIdleWarningDelayBattery[] = "Battery.Delays.IdleWarning";
const char kIdleDelayBattery[] = "Battery.Delays.Idle";
const char kIdleActionBattery[] = "Battery.IdleAction";

const char kScreenLockDelayAC[] = "AC";
const char kScreenLockDelayBattery[] = "Battery";

const char kActionSuspend[] = "Suspend";
const char kActionLogout[] = "Logout";
const char kActionShutdown[]  = "Shutdown";
const char kActionDoNothing[] = "DoNothing";

scoped_ptr<base::Value> GetValue(const base::DictionaryValue* dict,
                                 const char* key) {
  const base::Value* value = NULL;
  if (!dict->Get(key, &value))
    return scoped_ptr<base::Value>();
  return scoped_ptr<base::Value>(value->DeepCopy());
}

scoped_ptr<base::Value> GetAction(const base::DictionaryValue* dict,
                                  const char* key) {
  scoped_ptr<base::Value> value = GetValue(dict, key);
  std::string action;
  if (!value || !value->GetAsString(&action))
    return scoped_ptr<base::Value>();
  if (action == kActionSuspend) {
    return scoped_ptr<base::Value>(new base::FundamentalValue(
        chromeos::PowerPolicyController::ACTION_SUSPEND));
  }
  if (action == kActionLogout) {
    return scoped_ptr<base::Value>(new base::FundamentalValue(
        chromeos::PowerPolicyController::ACTION_STOP_SESSION));
  }
  if (action == kActionShutdown) {
    return scoped_ptr<base::Value>(new base::FundamentalValue(
        chromeos::PowerPolicyController::ACTION_SHUT_DOWN));
  }
  if (action == kActionDoNothing) {
    return scoped_ptr<base::Value>(new base::FundamentalValue(
        chromeos::PowerPolicyController::ACTION_DO_NOTHING));
  }
  return scoped_ptr<base::Value>();
}

}  // namespace

ExternalDataPolicyHandler::ExternalDataPolicyHandler(const char* policy_name)
    : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_DICTIONARY) {
}

ExternalDataPolicyHandler::~ExternalDataPolicyHandler() {
}

bool ExternalDataPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
                                                    PolicyErrorMap* errors) {
  if (!TypeCheckingPolicyHandler::CheckPolicySettings(policies, errors))
    return false;

  const std::string policy = policy_name();
  const base::Value* value = policies.GetValue(policy);
  if (!value)
    return true;

  const base::DictionaryValue* dict = NULL;
  value->GetAsDictionary(&dict);
  if (!dict) {
    NOTREACHED();
    return false;
  }
  std::string url_string;
  std::string hash_string;
  if (!GetSubkeyString(*dict, errors, policy, kSubkeyURL, &url_string) ||
      !GetSubkeyString(*dict, errors, policy, kSubkeyHash, &hash_string)) {
    return false;
  }

  const GURL url(url_string);
  if (!url.is_valid()) {
    errors->AddError(policy, kSubkeyURL, IDS_POLICY_VALUE_FORMAT_ERROR);
    return false;
  }

  std::vector<uint8> hash;
  if (!base::HexStringToBytes(hash_string, &hash) ||
      hash.size() != crypto::kSHA256Length) {
    errors->AddError(policy, kSubkeyHash, IDS_POLICY_VALUE_FORMAT_ERROR);
    return false;
  }

  return true;
}

void ExternalDataPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
                                                    PrefValueMap* prefs) {
}

// static
NetworkConfigurationPolicyHandler*
NetworkConfigurationPolicyHandler::CreateForUserPolicy() {
  return new NetworkConfigurationPolicyHandler(
      key::kOpenNetworkConfiguration,
      onc::ONC_SOURCE_USER_POLICY,
      prefs::kOpenNetworkConfiguration);
}

// static
NetworkConfigurationPolicyHandler*
NetworkConfigurationPolicyHandler::CreateForDevicePolicy() {
  return new NetworkConfigurationPolicyHandler(
      key::kDeviceOpenNetworkConfiguration,
      onc::ONC_SOURCE_DEVICE_POLICY,
      prefs::kDeviceOpenNetworkConfiguration);
}

NetworkConfigurationPolicyHandler::~NetworkConfigurationPolicyHandler() {}

bool NetworkConfigurationPolicyHandler::CheckPolicySettings(
    const PolicyMap& policies,
    PolicyErrorMap* errors) {
  const base::Value* value;
  if (!CheckAndGetValue(policies, errors, &value))
    return false;

  if (value) {
    std::string onc_blob;
    value->GetAsString(&onc_blob);
    scoped_ptr<base::DictionaryValue> root_dict =
        chromeos::onc::ReadDictionaryFromJson(onc_blob);
    if (root_dict.get() == NULL) {
      errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_PARSE_FAILED);
      return false;
    }

    // Validate the ONC dictionary. We are liberal and ignore unknown field
    // names and ignore invalid field names in kRecommended arrays.
    chromeos::onc::Validator validator(
        false,  // Ignore unknown fields.
        false,  // Ignore invalid recommended field names.
        true,   // Fail on missing fields.
        true);  // Validate for managed ONC
    validator.SetOncSource(onc_source_);

    // ONC policies are always unencrypted.
    chromeos::onc::Validator::Result validation_result;
    root_dict = validator.ValidateAndRepairObject(
        &chromeos::onc::kToplevelConfigurationSignature, *root_dict,
        &validation_result);
    if (validation_result == chromeos::onc::Validator::VALID_WITH_WARNINGS)
      errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_IMPORT_PARTIAL);
    else if (validation_result == chromeos::onc::Validator::INVALID)
      errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_IMPORT_FAILED);

    // In any case, don't reject the policy as some networks or certificates
    // could still be applied.
  }

  return true;
}

void NetworkConfigurationPolicyHandler::ApplyPolicySettings(
    const PolicyMap& policies,
    PrefValueMap* prefs) {
  const base::Value* value = policies.GetValue(policy_name());
  if (!value)
    return;

  std::string onc_blob;
  value->GetAsString(&onc_blob);

  scoped_ptr<base::ListValue> network_configs(new base::ListValue);
  base::ListValue certificates;
  base::DictionaryValue global_network_config;
  chromeos::onc::ParseAndValidateOncForImport(onc_blob,
                                              onc_source_,
                                              "",
                                              network_configs.get(),
                                              &global_network_config,
                                              &certificates);

  // Currently, only the per-network configuration is stored in a pref. Ignore
  // |global_network_config| and |certificates|.
  prefs->SetValue(pref_path_, network_configs.release());
}

void NetworkConfigurationPolicyHandler::PrepareForDisplaying(
    PolicyMap* policies) const {
  const PolicyMap::Entry* entry = policies->Get(policy_name());
  if (!entry)
    return;
  base::Value* sanitized_config = SanitizeNetworkConfig(entry->value);
  if (!sanitized_config)
    sanitized_config = base::Value::CreateNullValue();

  policies->Set(policy_name(), entry->level, entry->scope,
                sanitized_config, NULL);
}

NetworkConfigurationPolicyHandler::NetworkConfigurationPolicyHandler(
    const char* policy_name,
    onc::ONCSource onc_source,
    const char* pref_path)
    : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_STRING),
      onc_source_(onc_source),
      pref_path_(pref_path) {
}

// static
base::Value* NetworkConfigurationPolicyHandler::SanitizeNetworkConfig(
    const base::Value* config) {
  std::string json_string;
  if (!config->GetAsString(&json_string))
    return NULL;

  scoped_ptr<base::DictionaryValue> toplevel_dict =
      chromeos::onc::ReadDictionaryFromJson(json_string);
  if (!toplevel_dict)
    return NULL;

  // Placeholder to insert in place of the filtered setting.
  const char kPlaceholder[] = "********";

  toplevel_dict = chromeos::onc::MaskCredentialsInOncObject(
      chromeos::onc::kToplevelConfigurationSignature,
      *toplevel_dict,
      kPlaceholder);

  base::JSONWriter::WriteWithOptions(toplevel_dict.get(),
                                     base::JSONWriter::OPTIONS_PRETTY_PRINT,
                                     &json_string);
  return new base::StringValue(json_string);
}

PinnedLauncherAppsPolicyHandler::PinnedLauncherAppsPolicyHandler()
    : ExtensionListPolicyHandler(key::kPinnedLauncherApps,
                                 prefs::kPinnedLauncherApps,
                                 false) {}

PinnedLauncherAppsPolicyHandler::~PinnedLauncherAppsPolicyHandler() {}

void PinnedLauncherAppsPolicyHandler::ApplyPolicySettings(
    const PolicyMap& policies,
    PrefValueMap* prefs) {
  PolicyErrorMap errors;
  const base::Value* policy_value = policies.GetValue(policy_name());
  const base::ListValue* policy_list = NULL;
  if (policy_value && policy_value->GetAsList(&policy_list) && policy_list) {
    base::ListValue* pinned_apps_list = new base::ListValue();
    for (base::ListValue::const_iterator entry(policy_list->begin());
         entry != policy_list->end(); ++entry) {
      std::string id;
      if ((*entry)->GetAsString(&id)) {
        base::DictionaryValue* app_dict = new base::DictionaryValue();
        app_dict->SetString(ash::kPinnedAppsPrefAppIDPath, id);
        pinned_apps_list->Append(app_dict);
      }
    }
    prefs->SetValue(pref_path(), pinned_apps_list);
  }
}

ScreenMagnifierPolicyHandler::ScreenMagnifierPolicyHandler()
    : IntRangePolicyHandlerBase(key::kScreenMagnifierType,
                                0, ash::MAGNIFIER_FULL, false) {
}

ScreenMagnifierPolicyHandler::~ScreenMagnifierPolicyHandler() {
}

void ScreenMagnifierPolicyHandler::ApplyPolicySettings(
    const PolicyMap& policies,
    PrefValueMap* prefs) {
  const base::Value* value = policies.GetValue(policy_name());
  int value_in_range;
  if (value && EnsureInRange(value, &value_in_range, NULL)) {
    prefs->SetValue(prefs::kScreenMagnifierEnabled,
                    new base::FundamentalValue(value_in_range != 0));
    prefs->SetValue(prefs::kScreenMagnifierType,
                    new base::FundamentalValue(value_in_range));
  }
}

LoginScreenPowerManagementPolicyHandler::
    LoginScreenPowerManagementPolicyHandler(const Schema& chrome_schema)
    : SchemaValidatingPolicyHandler(key::kDeviceLoginScreenPowerManagement,
                                    chrome_schema.GetKnownProperty(
                                        key::kDeviceLoginScreenPowerManagement),
                                    SCHEMA_ALLOW_UNKNOWN) {
}

LoginScreenPowerManagementPolicyHandler::
    ~LoginScreenPowerManagementPolicyHandler() {
}

void LoginScreenPowerManagementPolicyHandler::ApplyPolicySettings(
    const PolicyMap& policies,
    PrefValueMap* prefs) {
}

DeprecatedIdleActionHandler::DeprecatedIdleActionHandler()
    : IntRangePolicyHandlerBase(
          key::kIdleAction,
          chromeos::PowerPolicyController::ACTION_SUSPEND,
          chromeos::PowerPolicyController::ACTION_DO_NOTHING,
          false) {}

DeprecatedIdleActionHandler::~DeprecatedIdleActionHandler() {}

void DeprecatedIdleActionHandler::ApplyPolicySettings(const PolicyMap& policies,
                                                      PrefValueMap* prefs) {
  const base::Value* value = policies.GetValue(policy_name());
  if (value && EnsureInRange(value, NULL, NULL)) {
    if (!prefs->GetValue(prefs::kPowerAcIdleAction, NULL))
      prefs->SetValue(prefs::kPowerAcIdleAction, value->DeepCopy());
    if (!prefs->GetValue(prefs::kPowerBatteryIdleAction, NULL))
      prefs->SetValue(prefs::kPowerBatteryIdleAction, value->DeepCopy());
  }
}

PowerManagementIdleSettingsPolicyHandler::
    PowerManagementIdleSettingsPolicyHandler(const Schema& chrome_schema)
    : SchemaValidatingPolicyHandler(
          key::kPowerManagementIdleSettings,
          chrome_schema.GetKnownProperty(key::kPowerManagementIdleSettings),
          SCHEMA_ALLOW_UNKNOWN) {
}

PowerManagementIdleSettingsPolicyHandler::
    ~PowerManagementIdleSettingsPolicyHandler() {
}

void PowerManagementIdleSettingsPolicyHandler::ApplyPolicySettings(
    const PolicyMap& policies,
    PrefValueMap* prefs) {
  scoped_ptr<base::Value> policy_value;
  if (!CheckAndGetValue(policies, NULL, &policy_value))
    return;
  const base::DictionaryValue* dict = NULL;
  if (!policy_value->GetAsDictionary(&dict)) {
    NOTREACHED();
    return;
  }
  scoped_ptr<base::Value> value;

  value = GetValue(dict, kScreenDimDelayAC);
  if (value)
    prefs->SetValue(prefs::kPowerAcScreenDimDelayMs, value.release());
  value = GetValue(dict, kScreenOffDelayAC);
  if (value)
    prefs->SetValue(prefs::kPowerAcScreenOffDelayMs, value.release());
  value = GetValue(dict, kIdleWarningDelayAC);
  if (value)
    prefs->SetValue(prefs::kPowerAcIdleWarningDelayMs, value.release());
  value = GetValue(dict, kIdleDelayAC);
  if (value)
    prefs->SetValue(prefs::kPowerAcIdleDelayMs, value.release());
  value = GetAction(dict, kIdleActionAC);
  if (value)
    prefs->SetValue(prefs::kPowerAcIdleAction, value.release());

  value = GetValue(dict, kScreenDimDelayBattery);
  if (value)
    prefs->SetValue(prefs::kPowerBatteryScreenDimDelayMs, value.release());
  value = GetValue(dict, kScreenOffDelayBattery);
  if (value)
    prefs->SetValue(prefs::kPowerBatteryScreenOffDelayMs, value.release());
  value = GetValue(dict, kIdleWarningDelayBattery);
  if (value)
    prefs->SetValue(prefs::kPowerBatteryIdleWarningDelayMs, value.release());
  value = GetValue(dict, kIdleDelayBattery);
  if (value)
    prefs->SetValue(prefs::kPowerBatteryIdleDelayMs, value.release());
  value = GetAction(dict, kIdleActionBattery);
  if (value)
    prefs->SetValue(prefs::kPowerBatteryIdleAction, value.release());
}

ScreenLockDelayPolicyHandler::ScreenLockDelayPolicyHandler(
    const Schema& chrome_schema)
    : SchemaValidatingPolicyHandler(
          key::kScreenLockDelays,
          chrome_schema.GetKnownProperty(key::kScreenLockDelays),
          SCHEMA_ALLOW_UNKNOWN) {
}

ScreenLockDelayPolicyHandler::~ScreenLockDelayPolicyHandler() {
}

void ScreenLockDelayPolicyHandler::ApplyPolicySettings(
    const PolicyMap& policies,
    PrefValueMap* prefs) {
  scoped_ptr<base::Value> policy_value;
  if (!CheckAndGetValue(policies, NULL, &policy_value))
    return;
  const base::DictionaryValue* dict = NULL;
  if (!policy_value->GetAsDictionary(&dict)) {
    NOTREACHED();
    return;
  }
  scoped_ptr<base::Value> value;

  value = GetValue(dict, kScreenLockDelayAC);
  if (value)
    prefs->SetValue(prefs::kPowerAcScreenLockDelayMs, value.release());
  value = GetValue(dict, kScreenLockDelayBattery);
  if (value)
    prefs->SetValue(prefs::kPowerBatteryScreenLockDelayMs, value.release());
}

}  // namespace policy

/* [<][>][^][v][top][bottom][index][help] */