| // Copyright 2013 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 "components/policy/core/common/policy_test_utils.h" |
| |
| #include <string> |
| |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/callback.h" |
| #include "base/json/json_writer.h" |
| #include "base/logging.h" |
| #include "base/strings/sys_string_conversions.h" |
| #include "base/values.h" |
| #include "build/build_config.h" |
| #include "components/policy/core/common/policy_bundle.h" |
| |
| #if defined(OS_IOS) || defined(OS_MACOSX) |
| #include <CoreFoundation/CoreFoundation.h> |
| |
| #include "base/mac/scoped_cftyperef.h" |
| #endif |
| |
| namespace policy { |
| |
| PolicyDetailsMap::PolicyDetailsMap() {} |
| |
| PolicyDetailsMap::~PolicyDetailsMap() {} |
| |
| GetChromePolicyDetailsCallback PolicyDetailsMap::GetCallback() const { |
| return base::Bind(&PolicyDetailsMap::Lookup, base::Unretained(this)); |
| } |
| |
| void PolicyDetailsMap::SetDetails(const std::string& policy, |
| const PolicyDetails* details) { |
| map_[policy] = details; |
| } |
| |
| const PolicyDetails* PolicyDetailsMap::Lookup(const std::string& policy) const { |
| PolicyDetailsMapping::const_iterator it = map_.find(policy); |
| return it == map_.end() ? NULL : it->second; |
| } |
| |
| bool PolicyServiceIsEmpty(const PolicyService* service) { |
| const PolicyMap& map = service->GetPolicies( |
| PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())); |
| if (!map.empty()) { |
| base::DictionaryValue dict; |
| for (PolicyMap::const_iterator it = map.begin(); it != map.end(); ++it) |
| dict.SetWithoutPathExpansion(it->first, it->second.value->DeepCopy()); |
| LOG(WARNING) << "There are pre-existing policies in this machine: " << dict; |
| } |
| return map.empty(); |
| } |
| |
| #if defined(OS_IOS) || defined(OS_MACOSX) |
| CFPropertyListRef ValueToProperty(const base::Value& value) { |
| switch (value.GetType()) { |
| case base::Value::TYPE_NULL: |
| return kCFNull; |
| |
| case base::Value::TYPE_BOOLEAN: { |
| bool bool_value; |
| if (value.GetAsBoolean(&bool_value)) |
| return bool_value ? kCFBooleanTrue : kCFBooleanFalse; |
| break; |
| } |
| |
| case base::Value::TYPE_INTEGER: { |
| int int_value; |
| if (value.GetAsInteger(&int_value)) { |
| return CFNumberCreate( |
| kCFAllocatorDefault, kCFNumberIntType, &int_value); |
| } |
| break; |
| } |
| |
| case base::Value::TYPE_DOUBLE: { |
| double double_value; |
| if (value.GetAsDouble(&double_value)) { |
| return CFNumberCreate( |
| kCFAllocatorDefault, kCFNumberDoubleType, &double_value); |
| } |
| break; |
| } |
| |
| case base::Value::TYPE_STRING: { |
| std::string string_value; |
| if (value.GetAsString(&string_value)) |
| return base::SysUTF8ToCFStringRef(string_value); |
| break; |
| } |
| |
| case base::Value::TYPE_DICTIONARY: { |
| const base::DictionaryValue* dict_value; |
| if (value.GetAsDictionary(&dict_value)) { |
| // |dict| is owned by the caller. |
| CFMutableDictionaryRef dict = |
| CFDictionaryCreateMutable(kCFAllocatorDefault, |
| dict_value->size(), |
| &kCFTypeDictionaryKeyCallBacks, |
| &kCFTypeDictionaryValueCallBacks); |
| for (base::DictionaryValue::Iterator iterator(*dict_value); |
| !iterator.IsAtEnd(); iterator.Advance()) { |
| // CFDictionaryAddValue() retains both |key| and |value|, so make sure |
| // the references are balanced. |
| base::ScopedCFTypeRef<CFStringRef> key( |
| base::SysUTF8ToCFStringRef(iterator.key())); |
| base::ScopedCFTypeRef<CFPropertyListRef> cf_value( |
| ValueToProperty(iterator.value())); |
| if (cf_value) |
| CFDictionaryAddValue(dict, key, cf_value); |
| } |
| return dict; |
| } |
| break; |
| } |
| |
| case base::Value::TYPE_LIST: { |
| const base::ListValue* list; |
| if (value.GetAsList(&list)) { |
| CFMutableArrayRef array = |
| CFArrayCreateMutable(NULL, list->GetSize(), &kCFTypeArrayCallBacks); |
| for (const auto& entry : *list) { |
| // CFArrayAppendValue() retains |cf_value|, so make sure the reference |
| // created by ValueToProperty() is released. |
| base::ScopedCFTypeRef<CFPropertyListRef> cf_value( |
| ValueToProperty(*entry)); |
| if (cf_value) |
| CFArrayAppendValue(array, cf_value); |
| } |
| return array; |
| } |
| break; |
| } |
| |
| case base::Value::TYPE_BINARY: |
| // This type isn't converted (though it can be represented as CFData) |
| // because there's no equivalent JSON type, and policy values can only |
| // take valid JSON values. |
| break; |
| } |
| |
| return NULL; |
| } |
| #endif // defined(OS_IOS) || defined(OS_MACOSX) |
| |
| } // namespace policy |
| |
| std::ostream& operator<<(std::ostream& os, |
| const policy::PolicyBundle& bundle) { |
| os << "{" << std::endl; |
| for (policy::PolicyBundle::const_iterator iter = bundle.begin(); |
| iter != bundle.end(); ++iter) { |
| os << " \"" << iter->first << "\": " << *iter->second << "," << std::endl; |
| } |
| os << "}"; |
| return os; |
| } |
| |
| std::ostream& operator<<(std::ostream& os, policy::PolicyScope scope) { |
| switch (scope) { |
| case policy::POLICY_SCOPE_USER: { |
| os << "POLICY_SCOPE_USER"; |
| break; |
| } |
| case policy::POLICY_SCOPE_MACHINE: { |
| os << "POLICY_SCOPE_MACHINE"; |
| break; |
| } |
| default: { |
| os << "POLICY_SCOPE_UNKNOWN(" << int(scope) << ")"; |
| } |
| } |
| return os; |
| } |
| |
| std::ostream& operator<<(std::ostream& os, policy::PolicyLevel level) { |
| switch (level) { |
| case policy::POLICY_LEVEL_RECOMMENDED: { |
| os << "POLICY_LEVEL_RECOMMENDED"; |
| break; |
| } |
| case policy::POLICY_LEVEL_MANDATORY: { |
| os << "POLICY_LEVEL_MANDATORY"; |
| break; |
| } |
| default: { |
| os << "POLICY_LEVEL_UNKNOWN(" << int(level) << ")"; |
| } |
| } |
| return os; |
| } |
| |
| std::ostream& operator<<(std::ostream& os, policy::PolicyDomain domain) { |
| switch (domain) { |
| case policy::POLICY_DOMAIN_CHROME: { |
| os << "POLICY_DOMAIN_CHROME"; |
| break; |
| } |
| case policy::POLICY_DOMAIN_EXTENSIONS: { |
| os << "POLICY_DOMAIN_EXTENSIONS"; |
| break; |
| } |
| default: { |
| os << "POLICY_DOMAIN_UNKNOWN(" << int(domain) << ")"; |
| } |
| } |
| return os; |
| } |
| |
| std::ostream& operator<<(std::ostream& os, const policy::PolicyMap& policies) { |
| os << "{" << std::endl; |
| for (policy::PolicyMap::const_iterator iter = policies.begin(); |
| iter != policies.end(); ++iter) { |
| os << " \"" << iter->first << "\": " << iter->second << "," << std::endl; |
| } |
| os << "}"; |
| return os; |
| } |
| |
| std::ostream& operator<<(std::ostream& os, const policy::PolicyMap::Entry& e) { |
| std::string value; |
| base::JSONWriter::WriteWithOptions( |
| *e.value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &value); |
| os << "{" << std::endl |
| << " \"level\": " << e.level << "," << std::endl |
| << " \"scope\": " << e.scope << "," << std::endl |
| << " \"value\": " << value |
| << "}"; |
| return os; |
| } |
| |
| std::ostream& operator<<(std::ostream& os, const policy::PolicyNamespace& ns) { |
| os << ns.domain << "/" << ns.component_id; |
| return os; |
| } |