1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/managed_network_configuration_handler.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector>
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/guid.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/json/json_writer.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/location.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/ref_counted.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/stl_util.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/values.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/dbus_method_call_status.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/shill_manager_client.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/shill_profile_client.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/shill_service_client.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/network_configuration_handler.h"
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/network_event_log.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/network_handler_callbacks.h"
28b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chromeos/network/network_profile.h"
29b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chromeos/network/network_profile_handler.h"
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/network_state.h"
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/network_state_handler.h"
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/network_ui_data.h"
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/onc/onc_constants.h"
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/onc/onc_merger.h"
35ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chromeos/network/onc/onc_normalizer.h"
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/onc/onc_signature.h"
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/onc/onc_translator.h"
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/onc/onc_utils.h"
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/onc/onc_validator.h"
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "dbus/object_path.h"
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromeos {
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// These are error strings used for error callbacks. None of these error
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// messages are user-facing: they should only appear in logs.
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kInvalidUserSettingsMessage[] = "User settings are invalid.";
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kInvalidUserSettings[] = "Error.InvalidUserSettings";
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kNetworkAlreadyConfiguredMessage[] =
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "Network is already configured.";
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kNetworkAlreadyConfigured[] = "Error.NetworkAlreadyConfigured";
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kPoliciesNotInitializedMessage[] = "Policies not initialized.";
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kPoliciesNotInitialized[] = "Error.PoliciesNotInitialized";
56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char kProfileNotInitializedMessage[] = "Profile not initialized.";
57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char kProfileNotInitialized[] = "Error.ProflieNotInitialized";
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kSetOnUnconfiguredNetworkMessage[] =
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "Unable to modify properties of an unconfigured network.";
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kSetOnUnconfiguredNetwork[] = "Error.SetCalledOnUnconfiguredNetwork";
61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char kUnknownProfilePathMessage[] = "Profile path is unknown.";
62b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char kUnknownProfilePath[] = "Error.UnknownProfilePath";
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kUnknownServicePathMessage[] = "Service path is unknown.";
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kUnknownServicePath[] = "Error.UnknownServicePath";
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This fake credential contains a random postfix which is extremly unlikely to
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// be used by any user.
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kFakeCredential[] = "FAKE_CREDENTIAL_VPaJDV9x";
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
70b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)std::string ToDebugString(onc::ONCSource source,
71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                          const std::string& userhash) {
72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return source == onc::ONC_SOURCE_USER_POLICY ?
73b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      ("user policy of " + userhash) : "device policy";
74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
75b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RunErrorCallback(const std::string& service_path,
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      const std::string& error_name,
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      const std::string& error_message,
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      const network_handler::ErrorCallback& error_callback) {
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NET_LOG_ERROR(error_name, error_message);
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_callback.Run(
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_name,
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      make_scoped_ptr(
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          network_handler::CreateErrorData(service_path,
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           error_name,
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           error_message)));
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Sets the UIData property in |shill_dictionary| to the serialization of
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// |ui_data|.
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SetUIData(const NetworkUIData& ui_data,
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               base::DictionaryValue* shill_dictionary) {
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::DictionaryValue ui_data_dict;
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ui_data.FillDictionary(&ui_data_dict);
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string ui_data_blob;
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::JSONWriter::Write(&ui_data_dict, &ui_data_blob);
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  shill_dictionary->SetStringWithoutPathExpansion(flimflam::kUIDataProperty,
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                  ui_data_blob);
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A dummy callback to ignore the result of Shill calls.
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IgnoreString(const std::string& str) {
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void LogErrorWithDict(const tracked_objects::Location& from_where,
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      const std::string& error_name,
107a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                      scoped_ptr<base::DictionaryValue> error_data) {
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(ERROR) << from_where.ToString() << ": " << error_name;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void LogErrorMessage(const tracked_objects::Location& from_where,
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     const std::string& error_name,
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     const std::string& error_message) {
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(ERROR) << from_where.ToString() << ": " << error_message;
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Removes all kFakeCredential values from sensitive fields (determined by
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// onc::FieldIsCredential) of |onc_object|.
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RemoveFakeCredentials(
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const onc::OncValueSignature& signature,
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::DictionaryValue* onc_object) {
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::DictionaryValue::Iterator it(*onc_object);
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (!it.IsAtEnd()) {
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::Value* value = NULL;
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string field_name = it.key();
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // We need the non-const entry to remove nested values but DictionaryValue
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // has no non-const iterator.
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    onc_object->GetWithoutPathExpansion(field_name, &value);
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Advance before delete.
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    it.Advance();
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // If |value| is a dictionary, recurse.
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::DictionaryValue* nested_object = NULL;
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (value->GetAsDictionary(&nested_object)) {
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const onc::OncFieldSignature* field_signature =
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          onc::GetFieldSignature(signature, field_name);
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      RemoveFakeCredentials(*field_signature->value_signature,
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            nested_object);
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // If |value| is a string, check if it is a fake credential.
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string string_value;
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (value->GetAsString(&string_value) &&
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        onc::FieldIsCredential(signature, field_name)) {
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (string_value == kFakeCredential) {
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // The value wasn't modified by the UI, thus we remove the field to keep
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // the existing value that is stored in Shill.
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        onc_object->RemoveWithoutPathExpansion(field_name, NULL);
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Otherwise, the value is set and modified by the UI, thus we keep that
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // value to overwrite whatever is stored in Shill.
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Creates a Shill property dictionary from the given arguments. The resulting
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// dictionary will be sent to Shill by the caller. Depending on the profile
160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// type, |policy| is interpreted as the user or device policy and |settings| as
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the user or shared settings.
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<base::DictionaryValue> CreateShillConfiguration(
163b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const NetworkProfile& profile,
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& guid,
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue* policy,
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue* settings) {
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> effective;
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (policy) {
170b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (profile.type() == NetworkProfile::TYPE_SHARED) {
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      effective = onc::MergeSettingsAndPoliciesToEffective(
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          NULL,  // no user policy
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          policy,  // device policy
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          NULL,  // no user settings
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          settings);  // shared settings
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      onc_source = onc::ONC_SOURCE_DEVICE_POLICY;
177b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    } else if (profile.type() == NetworkProfile::TYPE_USER) {
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      effective = onc::MergeSettingsAndPoliciesToEffective(
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          policy,  // user policy
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          NULL,  // no device policy
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          settings,  // user settings
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          NULL);  // no shared settings
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      onc_source = onc::ONC_SOURCE_USER_POLICY;
184b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    } else {
185b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      NOTREACHED();
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (settings) {
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    effective.reset(settings->DeepCopy());
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // TODO(pneubeck): change to source ONC_SOURCE_USER
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    onc_source = onc::ONC_SOURCE_NONE;
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    NOTREACHED();
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    onc_source = onc::ONC_SOURCE_NONE;
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RemoveFakeCredentials(onc::kNetworkConfigurationSignature,
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        effective.get());
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  effective->SetStringWithoutPathExpansion(onc::network_config::kGUID, guid);
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
201ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Remove irrelevant fields.
202ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  onc::Normalizer normalizer(true /* remove recommended fields */);
203ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  effective = normalizer.NormalizeObject(&onc::kNetworkConfigurationSignature,
204ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                         *effective);
205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> shill_dictionary(
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature,
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     *effective));
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  shill_dictionary->SetStringWithoutPathExpansion(flimflam::kProfileProperty,
211b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                                  profile.path);
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<NetworkUIData> ui_data;
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (policy)
215a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ui_data = NetworkUIData::CreateFromONC(onc_source, *policy);
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ui_data.reset(new NetworkUIData());
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (settings) {
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Shill doesn't know that sensitive data is contained in the UIData
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // property and might write it into logs or other insecure places. Thus, we
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // have to remove or mask credentials.
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    //
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Shill's GetProperties doesn't return credentials. Masking credentials
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // instead of just removing them, allows remembering if a credential is set
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // or not.
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> sanitized_settings(
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        onc::MaskCredentialsInOncObject(onc::kNetworkConfigurationSignature,
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        *settings,
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        kFakeCredential));
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ui_data->set_user_settings(sanitized_settings.Pass());
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetUIData(*ui_data, shill_dictionary.get());
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(2) << "Created Shill properties: " << *shill_dictionary;
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return shill_dictionary.Pass();
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
241558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Returns true if |policy| matches |actual_network|, which must be part of a
242558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// ONC NetworkConfiguration. This should be the only such matching function
243558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// within Chrome. Shill does such matching in several functions for network
244558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// identification. For compatibility, we currently should stick to Shill's
245558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// matching behavior.
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool IsPolicyMatching(const base::DictionaryValue& policy,
247558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                      const base::DictionaryValue& actual_network) {
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string policy_type;
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  policy.GetStringWithoutPathExpansion(onc::network_config::kType,
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       &policy_type);
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string network_type;
252558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  actual_network.GetStringWithoutPathExpansion(onc::network_config::kType,
253558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                               &network_type);
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (policy_type != network_type)
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (network_type != onc::network_type::kWiFi)
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
260558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  const base::DictionaryValue* policy_wifi = NULL;
261558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  policy.GetDictionaryWithoutPathExpansion(onc::network_config::kWiFi,
262558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                           &policy_wifi);
263558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  const base::DictionaryValue* actual_wifi = NULL;
264558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  actual_network.GetDictionaryWithoutPathExpansion(onc::network_config::kWiFi,
265558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                                   &actual_wifi);
266558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!policy_wifi || !actual_wifi)
267558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return false;
268558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string policy_ssid;
270558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  policy_wifi->GetStringWithoutPathExpansion(onc::wifi::kSSID, &policy_ssid);
271558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  std::string actual_ssid;
272558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  actual_wifi->GetStringWithoutPathExpansion(onc::wifi::kSSID, &actual_ssid);
273558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return (policy_ssid == actual_ssid);
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
276558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Returns the policy from |policies| matching |actual_network|, if any exists.
277558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Returns NULL otherwise. |actual_network| must be part of a ONC
278558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// NetworkConfiguration.
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const base::DictionaryValue* FindMatchingPolicy(
280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const ManagedNetworkConfigurationHandler::GuidToPolicyMap &policies,
281558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    const base::DictionaryValue& actual_network) {
282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (ManagedNetworkConfigurationHandler::GuidToPolicyMap::const_iterator it =
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           policies.begin(); it != policies.end(); ++it) {
284558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    if (IsPolicyMatching(*it->second, actual_network))
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return it->second;
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return NULL;
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const base::DictionaryValue* GetByGUID(
291b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const ManagedNetworkConfigurationHandler::GuidToPolicyMap &policies,
292b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& guid) {
293b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ManagedNetworkConfigurationHandler::GuidToPolicyMap::const_iterator it =
294b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      policies.find(guid);
295b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (it == policies.end())
296b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return NULL;
297b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return it->second;
298b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
299b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void TranslatePropertiesToOncAndRunCallback(
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const network_handler::DictionaryResultCallback& callback,
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& service_path,
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& shill_properties) {
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> onc_network(
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      onc::TranslateShillServiceToONCPart(
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          shill_properties,
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &onc::kNetworkWithStateSignature));
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(service_path, *onc_network);
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
313ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// This class compares (entry point is Run()) |modified_policies| with the
314ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// existing entries in the provided Shill profile |profile|. It fetches all
315ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// entries in parallel (GetProfilePropertiesCallback), compares each entry with
316ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the current policies (GetEntryCallback) and adds all missing policies
317ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// (~PolicyApplicator).
318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochclass ManagedNetworkConfigurationHandler::PolicyApplicator
319ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    : public base::RefCounted<PolicyApplicator> {
320ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch public:
321ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  typedef ManagedNetworkConfigurationHandler::GuidToPolicyMap GuidToPolicyMap;
322ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
323ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // |modified_policies| must not be NULL and will be empty afterwards.
324ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  PolicyApplicator(base::WeakPtr<ManagedNetworkConfigurationHandler> handler,
325ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                   const NetworkProfile& profile,
326ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                   std::set<std::string>* modified_policies);
327ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
328ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  void Run();
329ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch private:
331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  friend class base::RefCounted<PolicyApplicator>;
332ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
333ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Called with the properties of the profile |profile_|. Requests the
334ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // properties of each entry, which are processed by GetEntryCallback.
335ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  void GetProfilePropertiesCallback(
336ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      const base::DictionaryValue& profile_properties);
337ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Called with the properties of the profile entry |entry|. Checks whether the
339ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // entry was previously managed, whether a current policy applies and then
340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // either updates, deletes or not touches the entry.
341ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  void GetEntryCallback(const std::string& entry,
342ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                        const base::DictionaryValue& entry_properties);
343ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
344ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Sends Shill the command to delete profile entry |entry| from |profile_|.
345ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  void DeleteEntry(const std::string& entry);
346ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
347ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Creates new entries for all remaining policies, i.e. for which not matching
348ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // entry was found.
349ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  virtual ~PolicyApplicator();
350ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
351ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  std::set<std::string> remaining_policies_;
352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<ManagedNetworkConfigurationHandler> handler_;
353ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  NetworkProfile profile_;
354ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
355ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(PolicyApplicator);
356ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch};
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
358a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// static
359a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)scoped_ptr<NetworkUIData> ManagedNetworkConfigurationHandler::GetUIData(
360a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const base::DictionaryValue& shill_dictionary) {
361a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  std::string ui_data_blob;
362a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (shill_dictionary.GetStringWithoutPathExpansion(
363a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          flimflam::kUIDataProperty,
364a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          &ui_data_blob) &&
365a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      !ui_data_blob.empty()) {
366a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> ui_data_dict =
367a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        onc::ReadDictionaryFromJson(ui_data_blob);
368a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (ui_data_dict)
369a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return make_scoped_ptr(new NetworkUIData(*ui_data_dict));
370a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    else
371a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      LOG(ERROR) << "UIData is not a valid JSON dictionary.";
372a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
373a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  VLOG(2) << "JSON dictionary has no UIData blob: " << shill_dictionary;
374a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return scoped_ptr<NetworkUIData>();
375a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
376a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ManagedNetworkConfigurationHandler::GetManagedProperties(
378b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& userhash,
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& service_path,
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const network_handler::DictionaryResultCallback& callback,
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const network_handler::ErrorCallback& error_callback) {
382b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!GetPoliciesForUser(userhash) || !GetPoliciesForUser(std::string())) {
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RunErrorCallback(service_path,
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     kPoliciesNotInitialized,
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     kPoliciesNotInitializedMessage,
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     error_callback);
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  network_configuration_handler_->GetProperties(
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      service_path,
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &ManagedNetworkConfigurationHandler::GetManagedPropertiesCallback,
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          weak_ptr_factory_.GetWeakPtr(),
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          callback,
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          error_callback),
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_callback);
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ManagedNetworkConfigurationHandler::GetManagedPropertiesCallback(
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const network_handler::DictionaryResultCallback& callback,
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const network_handler::ErrorCallback& error_callback,
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& service_path,
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& shill_properties) {
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string profile_path;
405b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  shill_properties.GetStringWithoutPathExpansion(flimflam::kProfileProperty,
406b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                                 &profile_path);
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LOG(ERROR) << "Profile: " << profile_path;
408b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  const NetworkProfile* profile =
40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      network_profile_handler_->GetProfileForPath(profile_path);
410b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!profile) {
41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) << "No or no known profile received for service "
412b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            << service_path << ".";
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<NetworkUIData> ui_data = GetUIData(shill_properties);
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::DictionaryValue* user_settings = NULL;
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::DictionaryValue* shared_settings = NULL;
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
420b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (ui_data && profile) {
421b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (profile->type() == NetworkProfile::TYPE_SHARED)
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      shared_settings = ui_data->user_settings();
423b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    else if (profile->type() == NetworkProfile::TYPE_USER)
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_settings = ui_data->user_settings();
425b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    else
426b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      NOTREACHED();
427b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  } else if (profile) {
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "Service " << service_path << " of profile "
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << profile_path << " contains no or no valid UIData.";
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // TODO(pneubeck): add a conversion of user configured entries of old
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // ChromeOS versions. We will have to use a heuristic to determine which
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // properties _might_ be user configured.
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> active_settings(
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      onc::TranslateShillServiceToONCPart(
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          shill_properties,
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &onc::kNetworkWithStateSignature));
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string guid;
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  active_settings->GetStringWithoutPathExpansion(onc::network_config::kGUID,
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                 &guid);
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::DictionaryValue* user_policy = NULL;
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::DictionaryValue* device_policy = NULL;
446b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!guid.empty() && profile) {
447b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const GuidToPolicyMap* policies = GetPoliciesForProfile(*profile);
448b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!policies) {
449b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      RunErrorCallback(service_path,
450b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                       kPoliciesNotInitialized,
451b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                       kPoliciesNotInitializedMessage,
452b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                       error_callback);
453b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return;
454b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
455b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const base::DictionaryValue* policy = GetByGUID(*policies, guid);
456b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (profile->type() == NetworkProfile::TYPE_SHARED)
457b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      device_policy = policy;
458b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    else if (profile->type() == NetworkProfile::TYPE_USER)
459b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      user_policy = policy;
460b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    else
461b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      NOTREACHED();
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This call also removes credentials from policies.
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> augmented_properties =
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      onc::MergeSettingsAndPoliciesToAugmented(
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          onc::kNetworkConfigurationSignature,
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          user_policy,
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          device_policy,
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          user_settings,
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          shared_settings,
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          active_settings.get());
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(service_path, *augmented_properties);
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ManagedNetworkConfigurationHandler::GetProperties(
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& service_path,
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const network_handler::DictionaryResultCallback& callback,
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const network_handler::ErrorCallback& error_callback) const {
48090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  network_configuration_handler_->GetProperties(
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      service_path,
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&TranslatePropertiesToOncAndRunCallback, callback),
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_callback);
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ManagedNetworkConfigurationHandler::SetProperties(
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& service_path,
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& user_settings,
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const network_handler::ErrorCallback& error_callback) const {
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const NetworkState* state =
49290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      network_state_handler_->GetNetworkState(service_path);
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!state) {
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RunErrorCallback(service_path,
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     kUnknownServicePath,
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     kUnknownServicePathMessage,
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     error_callback);
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string guid = state->guid();
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (guid.empty()) {
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // TODO(pneubeck): create an initial configuration in this case. As for
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // CreateConfiguration, user settings from older ChromeOS versions have to
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // determined here.
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RunErrorCallback(service_path,
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     kSetOnUnconfiguredNetwork,
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     kSetOnUnconfiguredNetworkMessage,
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     error_callback);
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
514b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  const std::string& profile_path = state->profile_path();
515b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  const NetworkProfile *profile =
51690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      network_profile_handler_->GetProfileForPath(profile_path);
517b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!profile) {
518b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    RunErrorCallback(service_path,
519b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                     kUnknownProfilePath,
520b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                     kUnknownProfilePathMessage,
521b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                     error_callback);
522b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return;
523b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
524b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
525b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(2) << "SetProperties: Found GUID " << guid << " and profile "
526b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          << profile->ToDebugString();
527b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
528b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  const GuidToPolicyMap* policies = GetPoliciesForProfile(*profile);
529b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!policies) {
530b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    RunErrorCallback(service_path,
531b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                     kPoliciesNotInitialized,
532b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                     kPoliciesNotInitializedMessage,
533b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                     error_callback);
534b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return;
535b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
536b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Validate the ONC dictionary. We are liberal and ignore unknown field
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // names. User settings are only partial ONC, thus we ignore missing fields.
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  onc::Validator validator(false,  // Ignore unknown fields.
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           false,  // Ignore invalid recommended field names.
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           false,  // Ignore missing fields.
542ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                           false);  // This ONC does not come from policy.
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  onc::Validator::Result validation_result;
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> validated_user_settings =
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      validator.ValidateAndRepairObject(
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &onc::kNetworkConfigurationSignature,
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          user_settings,
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &validation_result);
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (validation_result == onc::Validator::INVALID) {
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RunErrorCallback(service_path,
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     kInvalidUserSettings,
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     kInvalidUserSettingsMessage,
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     error_callback);
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (validation_result == onc::Validator::VALID_WITH_WARNINGS)
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "Validation of ONC user settings produced warnings.";
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
561b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  const base::DictionaryValue* policy = GetByGUID(*policies, guid);
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(2) << "This configuration is " << (policy ? "" : "not ") << "managed.";
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
564ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<base::DictionaryValue> shill_dictionary(CreateShillConfiguration(
565ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      *profile, guid, policy, validated_user_settings.get()));
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  network_configuration_handler_->SetProperties(
56890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      service_path, *shill_dictionary, callback, error_callback);
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ManagedNetworkConfigurationHandler::CreateConfiguration(
572b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& userhash,
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& properties,
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const network_handler::StringResultCallback& callback,
575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const network_handler::ErrorCallback& error_callback) const {
576b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  const GuidToPolicyMap* policies = GetPoliciesForUser(userhash);
577b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!policies) {
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RunErrorCallback("",
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     kPoliciesNotInitialized,
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     kPoliciesNotInitializedMessage,
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     error_callback);
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
585b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (FindMatchingPolicy(*policies, properties)) {
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RunErrorCallback("",
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     kNetworkAlreadyConfigured,
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     kNetworkAlreadyConfiguredMessage,
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     error_callback);
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
592b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  const NetworkProfile* profile =
59390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      network_profile_handler_->GetProfileForUserhash(userhash);
594b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!profile) {
595b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    RunErrorCallback("",
596b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                     kProfileNotInitialized,
597b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                     kProfileNotInitializedMessage,
598b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                     error_callback);
599b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
600b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(pneubeck): In case of WiFi, check that no other configuration for the
602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // same {SSID, mode, security} exists. We don't support such multiple
603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // configurations, yet.
604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Generate a new GUID for this configuration. Ignore the maybe provided GUID
606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // in |properties| as it is not our own and from an untrusted source.
607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string guid = base::GenerateGUID();
608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> shill_dictionary(
609b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      CreateShillConfiguration(*profile, guid, NULL /*no policy*/,
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               &properties));
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
61290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  network_configuration_handler_->CreateConfiguration(
61390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *shill_dictionary, callback, error_callback);
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ManagedNetworkConfigurationHandler::RemoveConfiguration(
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& service_path,
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const network_handler::ErrorCallback& error_callback) const {
62090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  network_configuration_handler_->RemoveConfiguration(
62190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      service_path, callback, error_callback);
622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ManagedNetworkConfigurationHandler::SetPolicy(
625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    onc::ONCSource onc_source,
626b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& userhash,
627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::ListValue& network_configs_onc) {
628b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << "Setting policies from " << ToDebugString(onc_source, userhash)
629b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          << ".";
630b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
631b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // |userhash| must be empty for device policies.
632b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(onc_source != chromeos::onc::ONC_SOURCE_DEVICE_POLICY ||
633b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)         userhash.empty());
634b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  GuidToPolicyMap& policies = policies_by_user_[userhash];
635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
636b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  GuidToPolicyMap old_policies;
637b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  policies.swap(old_policies);
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This stores all GUIDs of policies that have changed or are new.
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::set<std::string> modified_policies;
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (base::ListValue::const_iterator it = network_configs_onc.begin();
643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       it != network_configs_onc.end(); ++it) {
644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue* network = NULL;
645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    (*it)->GetAsDictionary(&network);
646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(network);
647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string guid;
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    network->GetStringWithoutPathExpansion(onc::network_config::kGUID, &guid);
650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(!guid.empty());
651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
652b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (policies.count(guid) > 0) {
653b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      LOG(ERROR) << "ONC from " << ToDebugString(onc_source, userhash)
654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << " contains several entries for the same GUID "
655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << guid << ".";
656b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      delete policies[guid];
657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue* new_entry = network->DeepCopy();
659b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    policies[guid] = new_entry;
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue* old_entry = old_policies[guid];
662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!old_entry || !old_entry->Equals(new_entry))
663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      modified_policies.insert(guid);
664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  STLDeleteValues(&old_policies);
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
668b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  const NetworkProfile* profile =
66990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      network_profile_handler_->GetProfileForUserhash(userhash);
670b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!profile) {
671b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    VLOG(1) << "The relevant Shill profile isn't initialized yet, postponing "
672b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            << "policy application.";
673b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return;
674b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
675b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<PolicyApplicator> applicator = new PolicyApplicator(
677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_.GetWeakPtr(),
678b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      *profile,
679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &modified_policies);
680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  applicator->Run();
681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
683b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ManagedNetworkConfigurationHandler::OnProfileAdded(
684b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const NetworkProfile& profile) {
685b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << "Adding profile " << profile.ToDebugString() << "'.";
686b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
687b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  const GuidToPolicyMap* policies = GetPoliciesForProfile(profile);
688b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!policies) {
689b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    VLOG(1) << "The relevant policy is not initialized, "
690b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            << "postponing policy application.";
691b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return;
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
693b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
694b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  std::set<std::string> policy_guids;
695b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (GuidToPolicyMap::const_iterator it = policies->begin();
696b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)       it != policies->end(); ++it) {
697b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    policy_guids.insert(it->first);
698b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
699b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
700b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_refptr<PolicyApplicator> applicator = new PolicyApplicator(
701b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      weak_ptr_factory_.GetWeakPtr(),
702b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      profile,
703b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      &policy_guids);
704b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  applicator->Run();
705b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
706b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
707ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochconst base::DictionaryValue*
708ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochManagedNetworkConfigurationHandler::FindPolicyByGUID(
709ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string userhash,
710ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& guid,
711ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    onc::ONCSource* onc_source) const {
712ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  *onc_source = onc::ONC_SOURCE_NONE;
713ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
714ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!userhash.empty()) {
715ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const GuidToPolicyMap* user_policies = GetPoliciesForUser(userhash);
716ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (user_policies) {
717ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      GuidToPolicyMap::const_iterator found = user_policies->find(guid);
718ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (found != user_policies->end()) {
719ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        *onc_source = onc::ONC_SOURCE_USER_POLICY;
720ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        return found->second;
721ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      }
722ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
723ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
724ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
725ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const GuidToPolicyMap* device_policies = GetPoliciesForUser(std::string());
726ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (device_policies) {
727ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    GuidToPolicyMap::const_iterator found = device_policies->find(guid);
728ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (found != device_policies->end()) {
729ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      *onc_source = onc::ONC_SOURCE_DEVICE_POLICY;
730ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      return found->second;
731ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
732ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
733ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
734ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return NULL;
735ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
736ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
737b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ManagedNetworkConfigurationHandler::OnProfileRemoved(
738b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const NetworkProfile& profile) {
739b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Nothing to do in this case.
740b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
741b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
742b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const ManagedNetworkConfigurationHandler::GuidToPolicyMap*
743b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)ManagedNetworkConfigurationHandler::GetPoliciesForUser(
744b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& userhash) const {
745b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  UserToPoliciesMap::const_iterator it = policies_by_user_.find(userhash);
746b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (it == policies_by_user_.end())
747b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return NULL;
748b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return &it->second;
749c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
751b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const ManagedNetworkConfigurationHandler::GuidToPolicyMap*
752b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)ManagedNetworkConfigurationHandler::GetPoliciesForProfile(
753b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const NetworkProfile& profile) const {
754b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(profile.type() != NetworkProfile::TYPE_SHARED ||
755b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)         profile.userhash.empty());
756b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return GetPoliciesForUser(profile.userhash);
757b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
758b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
75990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)ManagedNetworkConfigurationHandler::ManagedNetworkConfigurationHandler()
76090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : network_state_handler_(NULL),
76190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      network_profile_handler_(NULL),
76290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      network_configuration_handler_(NULL),
763c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
764c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ManagedNetworkConfigurationHandler::~ManagedNetworkConfigurationHandler() {
76790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  network_profile_handler_->RemoveObserver(this);
768b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (UserToPoliciesMap::iterator it = policies_by_user_.begin();
769b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)       it != policies_by_user_.end(); ++it) {
770b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    STLDeleteValues(&it->second);
771b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
77490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ManagedNetworkConfigurationHandler::Init(
77590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    NetworkStateHandler* network_state_handler,
77690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    NetworkProfileHandler* network_profile_handler,
77790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    NetworkConfigurationHandler* network_configuration_handler) {
77890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  network_state_handler_ = network_state_handler;
77990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  network_profile_handler_ = network_profile_handler;
78090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  network_configuration_handler_ = network_configuration_handler;
78190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  network_profile_handler_->AddObserver(this);
78290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
78390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
784ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochManagedNetworkConfigurationHandler::PolicyApplicator::PolicyApplicator(
785ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    base::WeakPtr<ManagedNetworkConfigurationHandler> handler,
786ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const NetworkProfile& profile,
787ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    std::set<std::string>* modified_policies)
788ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    : handler_(handler), profile_(profile) {
789ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  remaining_policies_.swap(*modified_policies);
790ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
791ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
792ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ManagedNetworkConfigurationHandler::PolicyApplicator::Run() {
793ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DBusThreadManager::Get()->GetShillProfileClient()->GetProperties(
794ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      dbus::ObjectPath(profile_.path),
795ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      base::Bind(&PolicyApplicator::GetProfilePropertiesCallback, this),
796ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      base::Bind(&LogErrorMessage, FROM_HERE));
797ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
798ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
799ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ManagedNetworkConfigurationHandler::PolicyApplicator::
800ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    GetProfilePropertiesCallback(
801ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        const base::DictionaryValue& profile_properties) {
802ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!handler_) {
803ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LOG(WARNING) << "Handler destructed during policy application to profile "
804ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                 << profile_.ToDebugString();
805ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
806ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
807ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
808ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  VLOG(2) << "Received properties for profile " << profile_.ToDebugString();
809ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const base::ListValue* entries = NULL;
810ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!profile_properties.GetListWithoutPathExpansion(
811ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          flimflam::kEntriesProperty, &entries)) {
812ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LOG(ERROR) << "Profile " << profile_.ToDebugString()
813ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch               << " doesn't contain the property "
814ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch               << flimflam::kEntriesProperty;
815ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
816ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
817ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
818ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  for (base::ListValue::const_iterator it = entries->begin();
819ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch       it != entries->end();
820ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch       ++it) {
821ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    std::string entry;
822ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    (*it)->GetAsString(&entry);
823ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
824ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    std::ostringstream entry_failure;
825ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    DBusThreadManager::Get()->GetShillProfileClient()
826ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        ->GetEntry(dbus::ObjectPath(profile_.path),
827ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                   entry,
828ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                   base::Bind(&PolicyApplicator::GetEntryCallback, this, entry),
829ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                   base::Bind(&LogErrorMessage, FROM_HERE));
830ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
831ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
833ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ManagedNetworkConfigurationHandler::PolicyApplicator::GetEntryCallback(
834ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& entry,
835ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const base::DictionaryValue& entry_properties) {
836ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!handler_) {
837ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LOG(WARNING) << "Handler destructed during policy application to profile "
838ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                 << profile_.ToDebugString();
839ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
840ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
841ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
842ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  VLOG(2) << "Received properties for entry " << entry << " of profile "
843ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          << profile_.ToDebugString();
844ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
845ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<base::DictionaryValue> onc_part(
846ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      onc::TranslateShillServiceToONCPart(entry_properties,
847ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                          &onc::kNetworkWithStateSignature));
848ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
849ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  std::string old_guid;
850ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!onc_part->GetStringWithoutPathExpansion(onc::network_config::kGUID,
851ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                               &old_guid)) {
852ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    VLOG(1) << "Entry " << entry << " of profile " << profile_.ToDebugString()
853ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            << " doesn't contain a GUID.";
854ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // This might be an entry of an older ChromeOS version. Assume it to be
855ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // unmanaged.
856ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
857ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
858ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<NetworkUIData> ui_data = GetUIData(entry_properties);
859ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!ui_data) {
860ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    VLOG(1) << "Entry " << entry << " of profile " << profile_.ToDebugString()
861ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            << " contains no or no valid UIData.";
862ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // This might be an entry of an older ChromeOS version. Assume it to be
863ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // unmanaged. It's an inconsistency if there is a GUID but no UIData, thus
864ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // clear the GUID just in case.
865ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    old_guid.clear();
866ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
867ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
868ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  bool was_managed = !old_guid.empty() && ui_data &&
869ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                     (ui_data->onc_source() == onc::ONC_SOURCE_DEVICE_POLICY ||
870ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                      ui_data->onc_source() == onc::ONC_SOURCE_USER_POLICY);
871ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
872ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // The relevant policy must have been initialized, otherwise we hadn't Run
873ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // this PolicyApplicator.
874ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const GuidToPolicyMap& policies = *handler_->GetPoliciesForProfile(profile_);
875ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
876ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const base::DictionaryValue* new_policy = NULL;
877ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (was_managed) {
878ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // If we have a GUID that might match a current policy, do a lookup using
879ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // that GUID at first. In particular this is necessary, as some networks
880ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // can't be matched to policies by properties (e.g. VPN).
881ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    new_policy = GetByGUID(policies, old_guid);
882ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
883ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
884ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!new_policy) {
885ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // If we didn't find a policy by GUID, still a new policy might match.
886ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    new_policy = FindMatchingPolicy(policies, *onc_part);
887ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
888ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
889ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (new_policy) {
890ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    std::string new_guid;
891ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    new_policy->GetStringWithoutPathExpansion(onc::network_config::kGUID,
892ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                              &new_guid);
893ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
894ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    VLOG_IF(1, was_managed && old_guid != new_guid)
895ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        << "Updating configuration previously managed by policy " << old_guid
896ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        << " with new policy " << new_guid << ".";
897ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    VLOG_IF(1, !was_managed) << "Applying policy " << new_guid
898ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                             << " to previously unmanaged "
899ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                             << "configuration.";
900ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
901ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (old_guid == new_guid &&
902ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        remaining_policies_.find(new_guid) == remaining_policies_.end()) {
903ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      VLOG(1) << "Not updating existing managed configuration with guid "
904ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch              << new_guid << " because the policy didn't change.";
905ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    } else {
906ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      // Delete the entry to ensure that no old configuration remains.
907ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      // Don't do this if a policy is reapplied (e.g. after reboot) or updated
908ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      // (i.e. the GUID didn't change), in order to keep implicit state of
909ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      // Shill like "connected successfully before".
910ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (old_guid == new_guid) {
911ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        VLOG(1) << "Updating previously managed configuration with the "
912ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                << "updated policy " << new_guid << ".";
913ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      } else {
914ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        DeleteEntry(entry);
915ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      }
916ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
917ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      const base::DictionaryValue* user_settings =
918ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          ui_data ? ui_data->user_settings() : NULL;
919ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
920ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      // Write the new configuration.
921ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      scoped_ptr<base::DictionaryValue> shill_dictionary =
922ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          CreateShillConfiguration(
923ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch              profile_, new_guid, new_policy, user_settings);
924ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      handler_->network_configuration_handler()
925ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          ->CreateConfiguration(*shill_dictionary,
926ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                base::Bind(&IgnoreString),
927ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                base::Bind(&LogErrorWithDict, FROM_HERE));
928ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      remaining_policies_.erase(new_guid);
929ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
930ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  } else if (was_managed) {
931ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    VLOG(1) << "Removing configuration previously managed by policy "
932ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            << old_guid << ", because the policy was removed.";
933ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
934ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // Remove the entry, because the network was managed but isn't anymore.
935ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // Note: An alternative might be to preserve the user settings, but it's
936ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // unclear which values originating the policy should be removed.
937ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    DeleteEntry(entry);
938ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  } else {
939ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    VLOG(2) << "Ignore unmanaged entry.";
940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
941ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // The entry wasn't managed and doesn't match any current policy. Thus
942ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // leave it as it is.
943ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
944ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
945ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
946ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ManagedNetworkConfigurationHandler::PolicyApplicator::DeleteEntry(
947ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& entry) {
948ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DBusThreadManager::Get()->GetShillProfileClient()
949ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      ->DeleteEntry(dbus::ObjectPath(profile_.path),
950ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    entry,
951ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    base::Bind(&base::DoNothing),
952ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    base::Bind(&LogErrorMessage, FROM_HERE));
953ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
954ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
955ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochManagedNetworkConfigurationHandler::PolicyApplicator::~PolicyApplicator() {
956ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!handler_) {
957ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LOG(WARNING) << "Handler destructed during policy application to profile "
958ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                 << profile_.ToDebugString();
959ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
960ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
961ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
962ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (remaining_policies_.empty())
963ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
964ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
965ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  VLOG(2) << "Create new managed network configurations in profile"
966ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          << profile_.ToDebugString() << ".";
967ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // All profile entries were compared to policies. |configureGUIDs_| contains
968ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // all matched policies. From the remainder of policies, new configurations
969ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // have to be created.
970ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
971ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // The relevant policy must have been initialized, otherwise we hadn't Run
972ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // this PolicyApplicator.
973ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const GuidToPolicyMap& policies = *handler_->GetPoliciesForProfile(profile_);
974ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
975ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  for (std::set<std::string>::iterator it = remaining_policies_.begin();
976ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch       it != remaining_policies_.end();
977ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch       ++it) {
978ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const base::DictionaryValue* policy = GetByGUID(policies, *it);
979ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (!policy) {
980ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      LOG(ERROR) << "Policy " << *it << " doesn't exist anymore.";
981ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      continue;
982ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
983ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
984ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    VLOG(1) << "Creating new configuration managed by policy " << *it
985ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            << " in profile " << profile_.ToDebugString() << ".";
986ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
987ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    scoped_ptr<base::DictionaryValue> shill_dictionary =
988ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        CreateShillConfiguration(
989ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            profile_, *it, policy, NULL /* no user settings */);
990ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    handler_->network_configuration_handler()
991ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        ->CreateConfiguration(*shill_dictionary,
992ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                              base::Bind(&IgnoreString),
993ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                              base::Bind(&LogErrorWithDict, FROM_HERE));
994ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
995ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
996ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
997c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace chromeos
998