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