Index: chrome/browser/policy/user_policy_cache.cc |
diff --git a/chrome/browser/policy/user_policy_cache.cc b/chrome/browser/policy/user_policy_cache.cc |
index 12845f06aedf583b0152c199c3c994bd74d0be6d..ae14f83b48be6e70f7b12a96d7d36b6f31f63042 100644 |
--- a/chrome/browser/policy/user_policy_cache.cc |
+++ b/chrome/browser/policy/user_policy_cache.cc |
@@ -4,14 +4,18 @@ |
#include "chrome/browser/policy/user_policy_cache.h" |
+#include <limits> |
#include <string> |
#include "base/file_util.h" |
#include "base/logging.h" |
#include "base/task.h" |
+#include "base/values.h" |
+#include "chrome/browser/policy/configuration_policy_pref_store.h" |
#include "chrome/browser/policy/policy_map.h" |
#include "chrome/browser/policy/proto/cloud_policy.pb.h" |
#include "chrome/browser/policy/proto/device_management_local.pb.h" |
+#include "chrome/browser/policy/proto/old_generic_format.pb.h" |
#include "content/browser/browser_thread.h" |
#include "policy/configuration_policy_type.h" |
@@ -147,7 +151,144 @@ bool UserPolicyCache::DecodePolicyData(const em::PolicyData& policy_data, |
return false; |
} |
DecodePolicy(policy, mandatory, recommended); |
+ MaybeDecodeOldstylePolicy(policy_data.policy_value(), mandatory, recommended); |
return true; |
} |
+// Everything below is only needed for supporting old-style GenericNamedValue |
+// based policy data and can be removed once this support is no longer needed. |
+ |
+using google::protobuf::RepeatedField; |
+using google::protobuf::RepeatedPtrField; |
+ |
+class PolicyMapProxy : public ConfigurationPolicyStoreInterface { |
+ public: |
+ // Does not take ownership of |policy_map|, and callers need to make sure |
+ // that |policy_map| outlives this PolicyMapProxy. |
+ explicit PolicyMapProxy(PolicyMap* policy_map) |
+ : policy_map_(policy_map) {} |
+ virtual ~PolicyMapProxy() {} |
+ virtual void Apply(ConfigurationPolicyType policy, Value* value) { |
+ policy_map_->Set(policy, value); |
+ } |
+ |
+ private: |
+ PolicyMap* policy_map_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(PolicyMapProxy); |
+}; |
+ |
+void UserPolicyCache::MaybeDecodeOldstylePolicy( |
+ const std::string& policy_data, |
+ PolicyMap* mandatory, |
+ PolicyMap* recommended) { |
+ // Return immediately if we already have policy information in the maps. |
+ if (!mandatory->empty() || !recommended->empty()) |
+ return; |
+ em::LegacyChromeSettingsProto policy; |
+ // Return if the input string doesn't match the protobuf definition. |
+ if (!policy.ParseFromString(policy_data)) |
+ return; |
+ // Return if there's no old-style policy to decode. |
+ if (policy.named_value_size() == 0) |
+ return; |
+ |
+ // Inspect GenericNamedValues and decode them. |
+ DictionaryValue result; |
+ RepeatedPtrField<em::GenericNamedValue>::const_iterator named_value; |
+ for (named_value = policy.named_value().begin(); |
+ named_value != policy.named_value().end(); |
+ ++named_value) { |
+ if (named_value->has_value()) { |
+ Value* decoded_value = DecodeValue(named_value->value()); |
+ if (decoded_value) |
+ result.Set(named_value->name(), decoded_value); |
+ } |
+ } |
+ // Hack: Let one of the providers do the transformation from DictionaryValue |
+ // to PolicyMap, since they have the required code anyway. |
+ PolicyMapProxy map_proxy(mandatory); |
+ GetManagedPolicyProvider()->ApplyPolicyValueTree(&result, &map_proxy); |
+} |
+ |
+Value* UserPolicyCache::DecodeIntegerValue( |
+ google::protobuf::int64 value) const { |
+ if (value < std::numeric_limits<int>::min() || |
+ value > std::numeric_limits<int>::max()) { |
+ LOG(WARNING) << "Integer value " << value |
+ << " out of numeric limits, ignoring."; |
+ return NULL; |
+ } |
+ |
+ return Value::CreateIntegerValue(static_cast<int>(value)); |
+} |
+ |
+Value* UserPolicyCache::DecodeValue(const em::GenericValue& value) const { |
+ if (!value.has_value_type()) |
+ return NULL; |
+ |
+ switch (value.value_type()) { |
+ case em::GenericValue::VALUE_TYPE_BOOL: |
+ if (value.has_bool_value()) |
+ return Value::CreateBooleanValue(value.bool_value()); |
+ return NULL; |
+ case em::GenericValue::VALUE_TYPE_INT64: |
+ if (value.has_int64_value()) |
+ return DecodeIntegerValue(value.int64_value()); |
+ return NULL; |
+ case em::GenericValue::VALUE_TYPE_STRING: |
+ if (value.has_string_value()) |
+ return Value::CreateStringValue(value.string_value()); |
+ return NULL; |
+ case em::GenericValue::VALUE_TYPE_DOUBLE: |
+ if (value.has_double_value()) |
+ return Value::CreateDoubleValue(value.double_value()); |
+ return NULL; |
+ case em::GenericValue::VALUE_TYPE_BYTES: |
+ if (value.has_bytes_value()) { |
+ std::string bytes = value.bytes_value(); |
+ return BinaryValue::CreateWithCopiedBuffer(bytes.c_str(), bytes.size()); |
+ } |
+ return NULL; |
+ case em::GenericValue::VALUE_TYPE_BOOL_ARRAY: { |
+ ListValue* list = new ListValue; |
+ RepeatedField<bool>::const_iterator i; |
+ for (i = value.bool_array().begin(); i != value.bool_array().end(); ++i) |
+ list->Append(Value::CreateBooleanValue(*i)); |
+ return list; |
+ } |
+ case em::GenericValue::VALUE_TYPE_INT64_ARRAY: { |
+ ListValue* list = new ListValue; |
+ RepeatedField<google::protobuf::int64>::const_iterator i; |
+ for (i = value.int64_array().begin(); |
+ i != value.int64_array().end(); ++i) { |
+ Value* int_value = DecodeIntegerValue(*i); |
+ if (int_value) |
+ list->Append(int_value); |
+ } |
+ return list; |
+ } |
+ case em::GenericValue::VALUE_TYPE_STRING_ARRAY: { |
+ ListValue* list = new ListValue; |
+ RepeatedPtrField<std::string>::const_iterator i; |
+ for (i = value.string_array().begin(); |
+ i != value.string_array().end(); ++i) |
+ list->Append(Value::CreateStringValue(*i)); |
+ return list; |
+ } |
+ case em::GenericValue::VALUE_TYPE_DOUBLE_ARRAY: { |
+ ListValue* list = new ListValue; |
+ RepeatedField<double>::const_iterator i; |
+ for (i = value.double_array().begin(); |
+ i != value.double_array().end(); ++i) |
+ list->Append(Value::CreateDoubleValue(*i)); |
+ return list; |
+ } |
+ default: |
+ NOTREACHED() << "Unhandled value type"; |
+ } |
+ |
+ return NULL; |
+} |
+ |
} // namespace policy |