Chromium Code Reviews| Index: chrome/browser/chromeos/network_settings/onc_merger.cc |
| diff --git a/chrome/browser/chromeos/network_settings/onc_merger.cc b/chrome/browser/chromeos/network_settings/onc_merger.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..dc2a64758504e46ef46537adaf77d053a9a4b68d |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/network_settings/onc_merger.cc |
| @@ -0,0 +1,134 @@ |
| +// 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/network_settings/onc_merger.h" |
| + |
| +#include <set> |
| +#include <string> |
|
Mattias Nissler (ping if slow)
2012/09/18 16:29:08
newline
pneubeck (no reviews)
2012/10/02 15:03:02
Done.
|
| +#include "base/json/json_string_value_serializer.h" |
| +#include "base/logging.h" |
| +#include "base/values.h" |
| +#include "chrome/browser/chromeos/cros/onc_constants.h" |
| +#include "chrome/browser/chromeos/network_settings/onc_validator.h" |
| + |
| +namespace chromeos { |
| +namespace onc { |
| +namespace { |
| + |
| +base::DictionaryValue* Merge(const base::DictionaryValue* user, |
|
Mattias Nissler (ping if slow)
2012/09/18 16:29:08
should return a scoped_ptr<base::DictionaryValue>
pneubeck (no reviews)
2012/10/02 15:03:02
Done.
|
| + const base::DictionaryValue* policy) { |
|
Mattias Nissler (ping if slow)
2012/09/18 16:29:08
This function is too damn long. Please break into
pneubeck (no reviews)
2012/10/02 15:03:02
Done.
|
| + CHECK(policy != NULL || user != NULL); |
| + if (policy == NULL) return user->DeepCopy(); |
| + if (user == NULL) { |
| + // Don't DeepCopy but use Merge(,) to remove kRecommended fields. |
| + base::DictionaryValue emptyDictionary; |
| + return Merge(&emptyDictionary, policy); |
|
Mattias Nissler (ping if slow)
2012/09/18 16:29:08
so you're making a recursive call? Why not just us
pneubeck (no reviews)
2012/10/02 15:03:02
Done.
|
| + } |
| + |
| + base::DictionaryValue* result = new base::DictionaryValue(); |
| + |
| + // Get the names of the recommended fields. |
| + const ListValue* recommended_value = NULL; |
| + |
| + typedef std::set<std::string> RecommendedSet; |
| + RecommendedSet recommended; |
| + if (policy->GetListWithoutPathExpansion(kRecommended, |
| + &recommended_value)) { |
| + for (ListValue::const_iterator it = recommended_value->begin(); |
| + it != recommended_value->end(); ++it) { |
| + std::string entry; |
| + if ((*it)->GetAsString(&entry)) |
| + recommended.insert(entry); |
| + } |
| + } |
| + |
| + // Enforce all policy values that are not dictionaries. |
| + for (base::DictionaryValue::key_iterator it = policy->begin_keys(); |
| + it != policy->end_keys(); ++it) { |
| + const std::string& field_name = *it; |
| + if (field_name == kRecommended) |
| + continue; |
| + |
| + const base::Value* policy_value = NULL; |
| + policy->GetWithoutPathExpansion(field_name, &policy_value); |
| + |
| + if (policy_value->IsType(base::Value::TYPE_DICTIONARY)) |
| + continue; |
| + |
| + RecommendedSet::iterator recommended_it = |
| + recommended.find(field_name); |
| + |
| + bool is_recommended = recommended_it != recommended.end(); |
| + if (is_recommended) |
| + recommended.erase(recommended_it); |
| + |
| + bool will_overwrite = !(is_recommended && user->HasKey(field_name)); |
| + |
| + if (will_overwrite) { |
| + result->Set(field_name, policy_value->DeepCopy()); |
| + } else { |
| + const base::Value* user_value = NULL; |
| + user->GetWithoutPathExpansion(field_name, &user_value); |
| + DCHECK(user_value != NULL); |
| + result->Set(field_name, user_value->DeepCopy()); |
| + } |
| + } |
| + |
| + // Insert user values that overwrite empty recommended fields. |
| + for (RecommendedSet::iterator it = recommended.begin(); |
| + it != recommended.end(); ++it) { |
| + const std::string& field_name = *it; |
| + const base::Value* user_value = NULL; |
| + user->GetWithoutPathExpansion(field_name, &user_value); |
| + |
| + if (user_value != NULL) |
| + result->Set(field_name, user_value->DeepCopy()); |
| + } |
| + |
| + // Insert policy dictionaries and merge with user's dictionaries if existent. |
| + for (base::DictionaryValue::key_iterator it = policy->begin_keys(); |
| + it != policy->end_keys(); ++it) { |
| + const std::string& field_name = *it; |
| + |
| + const base::DictionaryValue* policy_value = NULL; |
| + if (!policy->GetDictionaryWithoutPathExpansion(field_name, &policy_value)) |
| + continue; |
| + |
| + const base::DictionaryValue* user_value = NULL; |
| + user->GetDictionaryWithoutPathExpansion(field_name, &user_value); |
| + result->Set(field_name, Merge(user_value, policy_value)); |
| + } |
| + |
| + // Insert user dictionaries not existent in the policy. |
| + for (base::DictionaryValue::key_iterator it = user->begin_keys(); |
| + it != user->end_keys(); ++it) { |
| + const std::string& field_name = *it; |
| + |
| + const base::DictionaryValue* user_value = NULL; |
| + if (!user->GetDictionaryWithoutPathExpansion(field_name, &user_value)) |
| + continue; |
| + |
| + const base::DictionaryValue* policy_value = NULL; |
| + if (policy->GetDictionaryWithoutPathExpansion(field_name, &policy_value)) |
| + continue; |
| + else |
| + result->Set(field_name, Merge(user_value, NULL)); |
| + } |
|
Mattias Nissler (ping if slow)
2012/09/18 16:29:08
Algorithm-wise, wouldn't it be simpler to start wi
pneubeck (no reviews)
2012/10/02 15:03:02
In that case, fields that only exist in user and a
|
| + |
| + return result; |
| +} |
| + |
| +} // namespace |
| + |
| +// static |
| +base::DictionaryValue* ONCMerger::MergeUserSettingsWithPolicy( |
| + const base::DictionaryValue& user, |
| + const base::DictionaryValue& policy) { |
| + base::DictionaryValue* result = Merge(&user, &policy); |
| + ONCValidator::RemoveIgnoredFieldsFromNetwork(result); |
| + return result; |
| +} |
| + |
| +} // namespace onc |
| +} // namespace chromeos |