[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / chromeos / network / onc / onc_merger.cc
blobfca8d37a3825e9e7e8afd13029b5f707ce08cc25
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromeos/network/onc/onc_merger.h"
7 #include <set>
8 #include <string>
10 #include "base/basictypes.h"
11 #include "base/logging.h"
12 #include "base/values.h"
13 #include "chromeos/network/onc/onc_constants.h"
15 namespace chromeos {
16 namespace onc {
17 namespace {
19 typedef scoped_ptr<base::DictionaryValue> DictionaryPtr;
21 // Inserts |true| at every field name in |result| that is recommended in policy.
22 void MarkRecommendedFieldnames(const base::DictionaryValue& policy,
23 base::DictionaryValue* result) {
24 const ListValue* recommended_value = NULL;
25 if (!policy.GetListWithoutPathExpansion(kRecommended, &recommended_value))
26 return;
27 for (ListValue::const_iterator it = recommended_value->begin();
28 it != recommended_value->end(); ++it) {
29 std::string entry;
30 if ((*it)->GetAsString(&entry))
31 result->SetBooleanWithoutPathExpansion(entry, true);
35 // Split the given |policy| into its recommended and mandatory settings. The
36 // dictionary |result_editable| contains a |true| value at each path that is
37 // editable by the user.
38 void SplitPolicy(const base::DictionaryValue& policy,
39 DictionaryPtr* result_recommended,
40 DictionaryPtr* result_editable,
41 DictionaryPtr* result_mandatory) {
42 result_recommended->reset(new base::DictionaryValue);
43 result_editable->reset(new base::DictionaryValue);
44 result_mandatory->reset(new base::DictionaryValue);
46 MarkRecommendedFieldnames(policy, result_editable->get());
48 // Distribute policy's entries into |result_recommended| and |result_editable|
49 // according to |result_editable| and recurse into nested dictionaries.
50 for (base::DictionaryValue::Iterator it(policy); it.HasNext(); it.Advance()) {
51 if (it.key() == kRecommended)
52 continue;
54 const base::DictionaryValue* child_policy = NULL;
55 if (it.value().GetAsDictionary(&child_policy)) {
56 DictionaryPtr child_recommended, child_editable, child_mandatory;
57 SplitPolicy(*child_policy, &child_recommended, &child_editable,
58 &child_mandatory);
60 (*result_recommended)->SetWithoutPathExpansion(
61 it.key(), child_recommended.release());
62 (*result_editable)->SetWithoutPathExpansion(
63 it.key(), child_editable.release());
64 (*result_mandatory)->SetWithoutPathExpansion(
65 it.key(), child_mandatory.release());
66 } else {
67 bool is_recommended = false;
68 (*result_editable)->GetBooleanWithoutPathExpansion(it.key(),
69 &is_recommended);
70 if (is_recommended) {
71 (*result_recommended)->SetWithoutPathExpansion(
72 it.key(), it.value().DeepCopy());
73 } else {
74 (*result_mandatory)->SetWithoutPathExpansion(
75 it.key(), it.value().DeepCopy());
81 // Copy values from |user| at paths that are assigned true in |editable|. The
82 // values are copied to a new dictionary which is returned.
83 DictionaryPtr DeepCopyIf(
84 const base::DictionaryValue& user,
85 const base::DictionaryValue& editable) {
86 DictionaryPtr result(new base::DictionaryValue);
88 for (base::DictionaryValue::Iterator it(user); it.HasNext(); it.Advance()) {
89 const base::DictionaryValue* user_child = NULL;
90 if (it.value().GetAsDictionary(&user_child)) {
91 const base::DictionaryValue* editable_child = NULL;
92 if (editable.GetDictionaryWithoutPathExpansion(it.key(),
93 &editable_child)) {
94 result->SetWithoutPathExpansion(
95 it.key(), DeepCopyIf(*user_child, *editable_child).release());
97 } else {
98 bool editable_flag;
99 if (editable.GetBooleanWithoutPathExpansion(it.key(), &editable_flag) &&
100 editable_flag) {
101 result->SetWithoutPathExpansion(it.key(), it.value().DeepCopy());
106 return result.Pass();
109 void MergeDictionaryIfNotNULL(const base::DictionaryValue* update,
110 base::DictionaryValue* result) {
111 if (update != NULL)
112 result->MergeDictionary(update);
115 } // namespace
117 DictionaryPtr MergeSettingsWithPolicies(
118 const base::DictionaryValue* user_policy,
119 const base::DictionaryValue* device_policy,
120 const base::DictionaryValue* user_onc,
121 const base::DictionaryValue* shared_onc) {
122 DictionaryPtr user_mandatory;
123 DictionaryPtr user_editable;
124 DictionaryPtr user_recommended;
125 if (user_policy != NULL) {
126 SplitPolicy(*user_policy, &user_recommended, &user_editable,
127 &user_mandatory);
128 } else {
129 user_mandatory.reset(new base::DictionaryValue);
130 user_recommended.reset(new base::DictionaryValue);
131 // 'user_editable == NULL' means everything is editable
134 DictionaryPtr device_mandatory;
135 DictionaryPtr device_editable;
136 DictionaryPtr device_recommended;
137 if (device_policy != NULL) {
138 SplitPolicy(*device_policy, &device_recommended, &device_editable,
139 &device_mandatory);
140 } else {
141 device_mandatory.reset(new base::DictionaryValue);
142 device_recommended.reset(new base::DictionaryValue);
143 // 'device_editable == NULL' means everything is editable
146 DictionaryPtr reduced_user_onc(
147 user_onc != NULL ? user_onc->DeepCopy() : new base::DictionaryValue);
148 if (user_editable.get() != NULL)
149 reduced_user_onc = DeepCopyIf(*reduced_user_onc, *user_editable);
150 if (device_editable.get() != NULL)
151 reduced_user_onc = DeepCopyIf(*reduced_user_onc, *device_editable);
153 DictionaryPtr reduced_shared_onc(
154 shared_onc != NULL ? shared_onc->DeepCopy() : new base::DictionaryValue);
155 if (user_editable.get() != NULL)
156 reduced_shared_onc = DeepCopyIf(*reduced_shared_onc, *user_editable);
157 if (device_editable.get() != NULL)
158 reduced_shared_onc = DeepCopyIf(*reduced_shared_onc, *device_editable);
160 // Merge the settings layers according to their priority: From lowest to
161 // highest priority.
162 DictionaryPtr result(new base::DictionaryValue);
163 MergeDictionaryIfNotNULL(device_recommended.get(), result.get());
164 MergeDictionaryIfNotNULL(user_recommended.get(), result.get());
165 MergeDictionaryIfNotNULL(reduced_shared_onc.get(), result.get());
166 MergeDictionaryIfNotNULL(reduced_user_onc.get(), result.get());
167 MergeDictionaryIfNotNULL(device_mandatory.get(), result.get());
168 MergeDictionaryIfNotNULL(user_mandatory.get(), result.get());
170 return result.Pass();
173 } // namespace onc
174 } // namespace chromeos