• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chromeos/network/managed_network_configuration_handler_impl.h"
6 
7 #include <set>
8 #include <vector>
9 
10 #include "base/bind.h"
11 #include "base/guid.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/stl_util.h"
17 #include "base/values.h"
18 #include "chromeos/dbus/shill_manager_client.h"
19 #include "chromeos/dbus/shill_profile_client.h"
20 #include "chromeos/dbus/shill_service_client.h"
21 #include "chromeos/network/device_state.h"
22 #include "chromeos/network/network_configuration_handler.h"
23 #include "chromeos/network/network_device_handler.h"
24 #include "chromeos/network/network_event_log.h"
25 #include "chromeos/network/network_policy_observer.h"
26 #include "chromeos/network/network_profile.h"
27 #include "chromeos/network/network_profile_handler.h"
28 #include "chromeos/network/network_state.h"
29 #include "chromeos/network/network_state_handler.h"
30 #include "chromeos/network/network_ui_data.h"
31 #include "chromeos/network/onc/onc_merger.h"
32 #include "chromeos/network/onc/onc_signature.h"
33 #include "chromeos/network/onc/onc_translator.h"
34 #include "chromeos/network/onc/onc_validator.h"
35 #include "chromeos/network/policy_util.h"
36 #include "chromeos/network/shill_property_util.h"
37 #include "components/onc/onc_constants.h"
38 #include "third_party/cros_system_api/dbus/service_constants.h"
39 
40 namespace chromeos {
41 
42 namespace {
43 
44 typedef std::map<std::string, const base::DictionaryValue*> GuidToPolicyMap;
45 
46 // These are error strings used for error callbacks. None of these error
47 // messages are user-facing: they should only appear in logs.
48 const char kInvalidUserSettings[] = "InvalidUserSettings";
49 const char kNetworkAlreadyConfigured[] = "NetworkAlreadyConfigured";
50 const char kPoliciesNotInitialized[] = "PoliciesNotInitialized";
51 const char kProfileNotInitialized[] = "ProflieNotInitialized";
52 const char kSetOnUnconfiguredNetwork[] = "SetCalledOnUnconfiguredNetwork";
53 const char kUnknownProfilePath[] = "UnknownProfilePath";
54 const char kUnknownNetwork[] = "UnknownNetwork";
55 
ToDebugString(::onc::ONCSource source,const std::string & userhash)56 std::string ToDebugString(::onc::ONCSource source,
57                           const std::string& userhash) {
58   return source == ::onc::ONC_SOURCE_USER_POLICY ?
59       ("user policy of " + userhash) : "device policy";
60 }
61 
InvokeErrorCallback(const std::string & service_path,const network_handler::ErrorCallback & error_callback,const std::string & error_name)62 void InvokeErrorCallback(const std::string& service_path,
63                          const network_handler::ErrorCallback& error_callback,
64                          const std::string& error_name) {
65   std::string error_msg = "ManagedConfig Error: " + error_name;
66   NET_LOG_ERROR(error_msg, service_path);
67   network_handler::RunErrorCallback(
68       error_callback, service_path, error_name, error_msg);
69 }
70 
LogErrorWithDict(const tracked_objects::Location & from_where,const std::string & error_name,scoped_ptr<base::DictionaryValue> error_data)71 void LogErrorWithDict(const tracked_objects::Location& from_where,
72                       const std::string& error_name,
73                       scoped_ptr<base::DictionaryValue> error_data) {
74   network_event_log::internal::AddEntry(
75        from_where.file_name(), from_where.line_number(),
76        network_event_log::LOG_LEVEL_ERROR,
77        error_name, "");
78 }
79 
GetByGUID(const GuidToPolicyMap & policies,const std::string & guid)80 const base::DictionaryValue* GetByGUID(const GuidToPolicyMap& policies,
81                                        const std::string& guid) {
82   GuidToPolicyMap::const_iterator it = policies.find(guid);
83   if (it == policies.end())
84     return NULL;
85   return it->second;
86 }
87 
88 }  // namespace
89 
90 struct ManagedNetworkConfigurationHandlerImpl::Policies {
91   ~Policies();
92 
93   GuidToPolicyMap per_network_config;
94   base::DictionaryValue global_network_config;
95 };
96 
~Policies()97 ManagedNetworkConfigurationHandlerImpl::Policies::~Policies() {
98   STLDeleteValues(&per_network_config);
99 }
100 
AddObserver(NetworkPolicyObserver * observer)101 void ManagedNetworkConfigurationHandlerImpl::AddObserver(
102     NetworkPolicyObserver* observer) {
103   observers_.AddObserver(observer);
104 }
105 
RemoveObserver(NetworkPolicyObserver * observer)106 void ManagedNetworkConfigurationHandlerImpl::RemoveObserver(
107     NetworkPolicyObserver* observer) {
108   observers_.RemoveObserver(observer);
109 }
110 
111 // GetManagedProperties
112 
GetManagedProperties(const std::string & userhash,const std::string & service_path,const network_handler::DictionaryResultCallback & callback,const network_handler::ErrorCallback & error_callback)113 void ManagedNetworkConfigurationHandlerImpl::GetManagedProperties(
114     const std::string& userhash,
115     const std::string& service_path,
116     const network_handler::DictionaryResultCallback& callback,
117     const network_handler::ErrorCallback& error_callback) {
118   if (!GetPoliciesForUser(userhash) || !GetPoliciesForUser(std::string())) {
119     InvokeErrorCallback(service_path, error_callback, kPoliciesNotInitialized);
120     return;
121   }
122   network_configuration_handler_->GetProperties(
123       service_path,
124       base::Bind(
125           &ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback,
126           weak_ptr_factory_.GetWeakPtr(),
127           base::Bind(
128               &ManagedNetworkConfigurationHandlerImpl::SendManagedProperties,
129               weak_ptr_factory_.GetWeakPtr(),
130               callback,
131               error_callback)),
132       error_callback);
133 }
134 
SendManagedProperties(const network_handler::DictionaryResultCallback & callback,const network_handler::ErrorCallback & error_callback,const std::string & service_path,scoped_ptr<base::DictionaryValue> shill_properties)135 void ManagedNetworkConfigurationHandlerImpl::SendManagedProperties(
136     const network_handler::DictionaryResultCallback& callback,
137     const network_handler::ErrorCallback& error_callback,
138     const std::string& service_path,
139     scoped_ptr<base::DictionaryValue> shill_properties) {
140   std::string profile_path;
141   shill_properties->GetStringWithoutPathExpansion(shill::kProfileProperty,
142                                                   &profile_path);
143   const NetworkProfile* profile =
144       network_profile_handler_->GetProfileForPath(profile_path);
145   if (!profile)
146     NET_LOG_ERROR("No profile for service: " + profile_path, service_path);
147 
148   scoped_ptr<NetworkUIData> ui_data =
149       shill_property_util::GetUIDataFromProperties(*shill_properties);
150 
151   const base::DictionaryValue* user_settings = NULL;
152   const base::DictionaryValue* shared_settings = NULL;
153 
154   if (ui_data && profile) {
155     if (profile->type() == NetworkProfile::TYPE_SHARED)
156       shared_settings = ui_data->user_settings();
157     else if (profile->type() == NetworkProfile::TYPE_USER)
158       user_settings = ui_data->user_settings();
159     else
160       NOTREACHED();
161   } else if (profile) {
162     NET_LOG_ERROR("Service contains empty or invalid UIData", service_path);
163     // TODO(pneubeck): add a conversion of user configured entries of old
164     // ChromeOS versions. We will have to use a heuristic to determine which
165     // properties _might_ be user configured.
166   }
167 
168   scoped_ptr<base::DictionaryValue> active_settings(
169       onc::TranslateShillServiceToONCPart(
170           *shill_properties,
171           &onc::kNetworkWithStateSignature));
172 
173   std::string guid;
174   active_settings->GetStringWithoutPathExpansion(::onc::network_config::kGUID,
175                                                  &guid);
176 
177   const base::DictionaryValue* user_policy = NULL;
178   const base::DictionaryValue* device_policy = NULL;
179   if (!guid.empty() && profile) {
180     const Policies* policies = GetPoliciesForProfile(*profile);
181     if (!policies) {
182       InvokeErrorCallback(
183           service_path, error_callback, kPoliciesNotInitialized);
184       return;
185     }
186     const base::DictionaryValue* policy =
187         GetByGUID(policies->per_network_config, guid);
188     if (profile->type() == NetworkProfile::TYPE_SHARED)
189       device_policy = policy;
190     else if (profile->type() == NetworkProfile::TYPE_USER)
191       user_policy = policy;
192     else
193       NOTREACHED();
194   }
195 
196   // This call also removes credentials from policies.
197   scoped_ptr<base::DictionaryValue> augmented_properties =
198       onc::MergeSettingsAndPoliciesToAugmented(
199           onc::kNetworkConfigurationSignature,
200           user_policy,
201           device_policy,
202           user_settings,
203           shared_settings,
204           active_settings.get());
205   callback.Run(service_path, *augmented_properties);
206 }
207 
208 // GetProperties
209 
GetProperties(const std::string & service_path,const network_handler::DictionaryResultCallback & callback,const network_handler::ErrorCallback & error_callback)210 void ManagedNetworkConfigurationHandlerImpl::GetProperties(
211     const std::string& service_path,
212     const network_handler::DictionaryResultCallback& callback,
213     const network_handler::ErrorCallback& error_callback) {
214   network_configuration_handler_->GetProperties(
215       service_path,
216       base::Bind(
217           &ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback,
218           weak_ptr_factory_.GetWeakPtr(),
219           base::Bind(&ManagedNetworkConfigurationHandlerImpl::SendProperties,
220                      weak_ptr_factory_.GetWeakPtr(),
221                      callback,
222                      error_callback)),
223       error_callback);
224 }
225 
SendProperties(const network_handler::DictionaryResultCallback & callback,const network_handler::ErrorCallback & error_callback,const std::string & service_path,scoped_ptr<base::DictionaryValue> shill_properties)226 void ManagedNetworkConfigurationHandlerImpl::SendProperties(
227     const network_handler::DictionaryResultCallback& callback,
228     const network_handler::ErrorCallback& error_callback,
229     const std::string& service_path,
230     scoped_ptr<base::DictionaryValue> shill_properties) {
231   scoped_ptr<base::DictionaryValue> onc_network(
232       onc::TranslateShillServiceToONCPart(*shill_properties,
233                                           &onc::kNetworkWithStateSignature));
234   callback.Run(service_path, *onc_network);
235 }
236 
237 // SetProperties
238 
SetProperties(const std::string & service_path,const base::DictionaryValue & user_settings,const base::Closure & callback,const network_handler::ErrorCallback & error_callback) const239 void ManagedNetworkConfigurationHandlerImpl::SetProperties(
240     const std::string& service_path,
241     const base::DictionaryValue& user_settings,
242     const base::Closure& callback,
243     const network_handler::ErrorCallback& error_callback) const {
244   const NetworkState* state =
245       network_state_handler_->GetNetworkStateFromServicePath(
246           service_path, true /* configured_only */);
247   if (!state) {
248     InvokeErrorCallback(service_path, error_callback, kUnknownNetwork);
249     return;
250   }
251 
252   std::string guid = state->guid();
253   if (guid.empty()) {
254     // TODO(pneubeck): create an initial configuration in this case. As for
255     // CreateConfiguration, user settings from older ChromeOS versions have to
256     // determined here.
257     InvokeErrorCallback(
258         service_path, error_callback, kSetOnUnconfiguredNetwork);
259     return;
260   }
261 
262   const std::string& profile_path = state->profile_path();
263   const NetworkProfile *profile =
264       network_profile_handler_->GetProfileForPath(profile_path);
265   if (!profile) {
266     InvokeErrorCallback(service_path, error_callback, kUnknownProfilePath);
267     return;
268   }
269 
270   VLOG(2) << "SetProperties: Found GUID " << guid << " and profile "
271           << profile->ToDebugString();
272 
273   const Policies* policies = GetPoliciesForProfile(*profile);
274   if (!policies) {
275     InvokeErrorCallback(service_path, error_callback, kPoliciesNotInitialized);
276     return;
277   }
278 
279   // Validate the ONC dictionary. We are liberal and ignore unknown field
280   // names. User settings are only partial ONC, thus we ignore missing fields.
281   onc::Validator validator(false,  // Ignore unknown fields.
282                            false,  // Ignore invalid recommended field names.
283                            false,  // Ignore missing fields.
284                            false);  // This ONC does not come from policy.
285 
286   onc::Validator::Result validation_result;
287   scoped_ptr<base::DictionaryValue> validated_user_settings =
288       validator.ValidateAndRepairObject(
289           &onc::kNetworkConfigurationSignature,
290           user_settings,
291           &validation_result);
292 
293   if (validation_result == onc::Validator::INVALID) {
294     InvokeErrorCallback(service_path, error_callback, kInvalidUserSettings);
295     return;
296   }
297   if (validation_result == onc::Validator::VALID_WITH_WARNINGS)
298     LOG(WARNING) << "Validation of ONC user settings produced warnings.";
299 
300   const base::DictionaryValue* policy =
301       GetByGUID(policies->per_network_config, guid);
302   VLOG(2) << "This configuration is " << (policy ? "" : "not ") << "managed.";
303 
304   scoped_ptr<base::DictionaryValue> shill_dictionary(
305       policy_util::CreateShillConfiguration(
306           *profile, guid, policy, validated_user_settings.get()));
307 
308   network_configuration_handler_->SetProperties(
309       service_path, *shill_dictionary, callback, error_callback);
310 }
311 
CreateConfiguration(const std::string & userhash,const base::DictionaryValue & properties,const network_handler::StringResultCallback & callback,const network_handler::ErrorCallback & error_callback) const312 void ManagedNetworkConfigurationHandlerImpl::CreateConfiguration(
313     const std::string& userhash,
314     const base::DictionaryValue& properties,
315     const network_handler::StringResultCallback& callback,
316     const network_handler::ErrorCallback& error_callback) const {
317   const Policies* policies = GetPoliciesForUser(userhash);
318   if (!policies) {
319     InvokeErrorCallback("", error_callback, kPoliciesNotInitialized);
320     return;
321   }
322 
323   if (policy_util::FindMatchingPolicy(policies->per_network_config,
324                                       properties)) {
325     InvokeErrorCallback("", error_callback, kNetworkAlreadyConfigured);
326     return;
327   }
328 
329   const NetworkProfile* profile =
330       network_profile_handler_->GetProfileForUserhash(userhash);
331   if (!profile) {
332     InvokeErrorCallback("", error_callback, kProfileNotInitialized);
333     return;
334   }
335 
336   // TODO(pneubeck): In case of WiFi, check that no other configuration for the
337   // same {SSID, mode, security} exists. We don't support such multiple
338   // configurations, yet.
339 
340   // Generate a new GUID for this configuration. Ignore the maybe provided GUID
341   // in |properties| as it is not our own and from an untrusted source.
342   std::string guid = base::GenerateGUID();
343   scoped_ptr<base::DictionaryValue> shill_dictionary(
344       policy_util::CreateShillConfiguration(
345           *profile, guid, NULL /*no policy*/, &properties));
346 
347   network_configuration_handler_->CreateConfiguration(
348       *shill_dictionary, callback, error_callback);
349 }
350 
RemoveConfiguration(const std::string & service_path,const base::Closure & callback,const network_handler::ErrorCallback & error_callback) const351 void ManagedNetworkConfigurationHandlerImpl::RemoveConfiguration(
352     const std::string& service_path,
353     const base::Closure& callback,
354     const network_handler::ErrorCallback& error_callback) const {
355   network_configuration_handler_->RemoveConfiguration(
356       service_path, callback, error_callback);
357 }
358 
SetPolicy(::onc::ONCSource onc_source,const std::string & userhash,const base::ListValue & network_configs_onc,const base::DictionaryValue & global_network_config)359 void ManagedNetworkConfigurationHandlerImpl::SetPolicy(
360     ::onc::ONCSource onc_source,
361     const std::string& userhash,
362     const base::ListValue& network_configs_onc,
363     const base::DictionaryValue& global_network_config) {
364   VLOG(1) << "Setting policies from " << ToDebugString(onc_source, userhash)
365           << ".";
366 
367   // |userhash| must be empty for device policies.
368   DCHECK(onc_source != ::onc::ONC_SOURCE_DEVICE_POLICY ||
369          userhash.empty());
370   Policies* policies = NULL;
371   if (ContainsKey(policies_by_user_, userhash)) {
372     policies = policies_by_user_[userhash].get();
373   } else {
374     policies = new Policies;
375     policies_by_user_[userhash] = make_linked_ptr(policies);
376   }
377 
378   policies->global_network_config.MergeDictionary(&global_network_config);
379 
380   GuidToPolicyMap old_per_network_config;
381   policies->per_network_config.swap(old_per_network_config);
382 
383   // This stores all GUIDs of policies that have changed or are new.
384   std::set<std::string> modified_policies;
385 
386   for (base::ListValue::const_iterator it = network_configs_onc.begin();
387        it != network_configs_onc.end(); ++it) {
388     const base::DictionaryValue* network = NULL;
389     (*it)->GetAsDictionary(&network);
390     DCHECK(network);
391 
392     std::string guid;
393     network->GetStringWithoutPathExpansion(::onc::network_config::kGUID, &guid);
394     DCHECK(!guid.empty());
395 
396     if (policies->per_network_config.count(guid) > 0) {
397       NET_LOG_ERROR("ONC from " + ToDebugString(onc_source, userhash) +
398                     " contains several entries for the same GUID ", guid);
399       delete policies->per_network_config[guid];
400     }
401     const base::DictionaryValue* new_entry = network->DeepCopy();
402     policies->per_network_config[guid] = new_entry;
403 
404     const base::DictionaryValue* old_entry = old_per_network_config[guid];
405     if (!old_entry || !old_entry->Equals(new_entry))
406       modified_policies.insert(guid);
407   }
408 
409   STLDeleteValues(&old_per_network_config);
410 
411   const NetworkProfile* profile =
412       network_profile_handler_->GetProfileForUserhash(userhash);
413   if (profile) {
414     scoped_refptr<PolicyApplicator> applicator =
415         new PolicyApplicator(weak_ptr_factory_.GetWeakPtr(),
416                              *profile,
417                              policies->per_network_config,
418                              policies->global_network_config,
419                              &modified_policies);
420     applicator->Run();
421   } else {
422     VLOG(1) << "The relevant Shill profile isn't initialized yet, postponing "
423             << "policy application.";
424     // See OnProfileAdded.
425   }
426 
427   FOR_EACH_OBSERVER(NetworkPolicyObserver, observers_, PolicyChanged(userhash));
428 }
429 
OnProfileAdded(const NetworkProfile & profile)430 void ManagedNetworkConfigurationHandlerImpl::OnProfileAdded(
431     const NetworkProfile& profile) {
432   VLOG(1) << "Adding profile " << profile.ToDebugString() << "'.";
433 
434   const Policies* policies = GetPoliciesForProfile(profile);
435   if (!policies) {
436     VLOG(1) << "The relevant policy is not initialized, "
437             << "postponing policy application.";
438     // See SetPolicy.
439     return;
440   }
441 
442   std::set<std::string> policy_guids;
443   for (GuidToPolicyMap::const_iterator it =
444            policies->per_network_config.begin();
445        it != policies->per_network_config.end(); ++it) {
446     policy_guids.insert(it->first);
447   }
448 
449   scoped_refptr<PolicyApplicator> applicator =
450       new PolicyApplicator(weak_ptr_factory_.GetWeakPtr(),
451                            profile,
452                            policies->per_network_config,
453                            policies->global_network_config,
454                            &policy_guids);
455   applicator->Run();
456 }
457 
OnProfileRemoved(const NetworkProfile & profile)458 void ManagedNetworkConfigurationHandlerImpl::OnProfileRemoved(
459     const NetworkProfile& profile) {
460   // Nothing to do in this case.
461 }
462 
CreateConfigurationFromPolicy(const base::DictionaryValue & shill_properties)463 void ManagedNetworkConfigurationHandlerImpl::CreateConfigurationFromPolicy(
464     const base::DictionaryValue& shill_properties) {
465   network_configuration_handler_->CreateConfiguration(
466       shill_properties,
467       base::Bind(
468           &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork,
469           weak_ptr_factory_.GetWeakPtr()),
470       base::Bind(&LogErrorWithDict, FROM_HERE));
471 }
472 
473 void ManagedNetworkConfigurationHandlerImpl::
UpdateExistingConfigurationWithPropertiesFromPolicy(const base::DictionaryValue & existing_properties,const base::DictionaryValue & new_properties)474     UpdateExistingConfigurationWithPropertiesFromPolicy(
475         const base::DictionaryValue& existing_properties,
476         const base::DictionaryValue& new_properties) {
477   base::DictionaryValue shill_properties;
478 
479   std::string profile;
480   existing_properties.GetStringWithoutPathExpansion(shill::kProfileProperty,
481                                                     &profile);
482   if (profile.empty()) {
483     NET_LOG_ERROR("Missing profile property",
484                   shill_property_util::GetNetworkIdFromProperties(
485                       existing_properties));
486     return;
487   }
488   shill_properties.SetStringWithoutPathExpansion(shill::kProfileProperty,
489                                                  profile);
490 
491   if (!shill_property_util::CopyIdentifyingProperties(
492           existing_properties,
493           true /* properties were read from Shill */,
494           &shill_properties)) {
495     NET_LOG_ERROR("Missing identifying properties",
496                   shill_property_util::GetNetworkIdFromProperties(
497                       existing_properties));
498   }
499 
500   shill_properties.MergeDictionary(&new_properties);
501 
502   network_configuration_handler_->CreateConfiguration(
503       shill_properties,
504       base::Bind(
505           &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork,
506           weak_ptr_factory_.GetWeakPtr()),
507       base::Bind(&LogErrorWithDict, FROM_HERE));
508 }
509 
OnPoliciesApplied()510 void ManagedNetworkConfigurationHandlerImpl::OnPoliciesApplied() {
511 }
512 
513 const base::DictionaryValue*
FindPolicyByGUID(const std::string userhash,const std::string & guid,::onc::ONCSource * onc_source) const514 ManagedNetworkConfigurationHandlerImpl::FindPolicyByGUID(
515     const std::string userhash,
516     const std::string& guid,
517     ::onc::ONCSource* onc_source) const {
518   *onc_source = ::onc::ONC_SOURCE_NONE;
519 
520   if (!userhash.empty()) {
521     const Policies* user_policies = GetPoliciesForUser(userhash);
522     if (user_policies) {
523       const base::DictionaryValue* policy =
524           GetByGUID(user_policies->per_network_config, guid);
525       if (policy) {
526         *onc_source = ::onc::ONC_SOURCE_USER_POLICY;
527         return policy;
528       }
529     }
530   }
531 
532   const Policies* device_policies = GetPoliciesForUser(std::string());
533   if (device_policies) {
534     const base::DictionaryValue* policy =
535         GetByGUID(device_policies->per_network_config, guid);
536     if (policy) {
537       *onc_source = ::onc::ONC_SOURCE_DEVICE_POLICY;
538       return policy;
539     }
540   }
541 
542   return NULL;
543 }
544 
545 const base::DictionaryValue*
GetGlobalConfigFromPolicy(const std::string userhash) const546 ManagedNetworkConfigurationHandlerImpl::GetGlobalConfigFromPolicy(
547     const std::string userhash) const {
548   const Policies* policies = GetPoliciesForUser(userhash);
549   if (!policies)
550     return NULL;
551 
552   return &policies->global_network_config;
553 }
554 const base::DictionaryValue*
FindPolicyByGuidAndProfile(const std::string & guid,const std::string & profile_path) const555 ManagedNetworkConfigurationHandlerImpl::FindPolicyByGuidAndProfile(
556     const std::string& guid,
557     const std::string& profile_path) const {
558   const NetworkProfile* profile =
559       network_profile_handler_->GetProfileForPath(profile_path);
560   if (!profile) {
561     NET_LOG_ERROR("Profile path unknown:" + profile_path, guid);
562     return NULL;
563   }
564 
565   const Policies* policies = GetPoliciesForProfile(*profile);
566   if (!policies)
567     return NULL;
568 
569   return GetByGUID(policies->per_network_config, guid);
570 }
571 
572 const ManagedNetworkConfigurationHandlerImpl::Policies*
GetPoliciesForUser(const std::string & userhash) const573 ManagedNetworkConfigurationHandlerImpl::GetPoliciesForUser(
574     const std::string& userhash) const {
575   UserToPoliciesMap::const_iterator it = policies_by_user_.find(userhash);
576   if (it == policies_by_user_.end())
577     return NULL;
578   return it->second.get();
579 }
580 
581 const ManagedNetworkConfigurationHandlerImpl::Policies*
GetPoliciesForProfile(const NetworkProfile & profile) const582 ManagedNetworkConfigurationHandlerImpl::GetPoliciesForProfile(
583     const NetworkProfile& profile) const {
584   DCHECK(profile.type() != NetworkProfile::TYPE_SHARED ||
585          profile.userhash.empty());
586   return GetPoliciesForUser(profile.userhash);
587 }
588 
ManagedNetworkConfigurationHandlerImpl()589 ManagedNetworkConfigurationHandlerImpl::ManagedNetworkConfigurationHandlerImpl()
590     : network_state_handler_(NULL),
591       network_profile_handler_(NULL),
592       network_configuration_handler_(NULL),
593       network_device_handler_(NULL),
594       weak_ptr_factory_(this) {}
595 
596 ManagedNetworkConfigurationHandlerImpl::
~ManagedNetworkConfigurationHandlerImpl()597     ~ManagedNetworkConfigurationHandlerImpl() {
598   network_profile_handler_->RemoveObserver(this);
599 }
600 
Init(NetworkStateHandler * network_state_handler,NetworkProfileHandler * network_profile_handler,NetworkConfigurationHandler * network_configuration_handler,NetworkDeviceHandler * network_device_handler)601 void ManagedNetworkConfigurationHandlerImpl::Init(
602     NetworkStateHandler* network_state_handler,
603     NetworkProfileHandler* network_profile_handler,
604     NetworkConfigurationHandler* network_configuration_handler,
605     NetworkDeviceHandler* network_device_handler) {
606   network_state_handler_ = network_state_handler;
607   network_profile_handler_ = network_profile_handler;
608   network_configuration_handler_ = network_configuration_handler;
609   network_device_handler_ = network_device_handler;
610   network_profile_handler_->AddObserver(this);
611 }
612 
OnPolicyAppliedToNetwork(const std::string & service_path)613 void ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork(
614     const std::string& service_path) {
615   if (service_path.empty())
616     return;
617   FOR_EACH_OBSERVER(
618       NetworkPolicyObserver, observers_, PolicyApplied(service_path));
619 }
620 
621 // Get{Managed}Properties helpers
622 
GetDeviceStateProperties(const std::string & service_path,base::DictionaryValue * properties)623 void ManagedNetworkConfigurationHandlerImpl::GetDeviceStateProperties(
624     const std::string& service_path,
625     base::DictionaryValue* properties) {
626   std::string connection_state;
627   properties->GetStringWithoutPathExpansion(
628       shill::kStateProperty, &connection_state);
629   if (!NetworkState::StateIsConnected(connection_state))
630     return;
631 
632   // Get the IPConfig properties from the device and store them in "IPConfigs"
633   // (plural) in the properties dictionary. (Note: Shill only provides a single
634   // "IPConfig" property for a network service, but a consumer of this API may
635   // want information about all ipv4 and ipv6 IPConfig properties.
636   std::string device;
637   properties->GetStringWithoutPathExpansion(shill::kDeviceProperty, &device);
638   const DeviceState* device_state =
639       network_state_handler_->GetDeviceState(device);
640   if (!device_state) {
641     NET_LOG_ERROR("GetDeviceProperties: no device: " + device, service_path);
642     return;
643   }
644 
645   // Get the hardware MAC address from the DeviceState.
646   if (!device_state->mac_address().empty()) {
647     properties->SetStringWithoutPathExpansion(
648         shill::kAddressProperty, device_state->mac_address());
649   }
650 
651   // Convert IPConfig dictionary to a ListValue.
652   base::ListValue* ip_configs = new base::ListValue;
653   for (base::DictionaryValue::Iterator iter(device_state->ip_configs());
654        !iter.IsAtEnd(); iter.Advance()) {
655     ip_configs->Append(iter.value().DeepCopy());
656   }
657   properties->SetWithoutPathExpansion(shill::kIPConfigsProperty, ip_configs);
658 }
659 
GetPropertiesCallback(GetDevicePropertiesCallback send_callback,const std::string & service_path,const base::DictionaryValue & shill_properties)660 void ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback(
661     GetDevicePropertiesCallback send_callback,
662     const std::string& service_path,
663     const base::DictionaryValue& shill_properties) {
664   scoped_ptr<base::DictionaryValue> shill_properties_copy(
665       shill_properties.DeepCopy());
666 
667   // Add associated Device properties before the ONC translation.
668   GetDeviceStateProperties(service_path, shill_properties_copy.get());
669 
670   // Only request Device properties for Cellular networks with a valid device.
671   std::string type, device_path;
672   if (!network_device_handler_ ||
673       !shill_properties_copy->GetStringWithoutPathExpansion(
674           shill::kTypeProperty, &type) ||
675       type != shill::kTypeCellular ||
676       !shill_properties_copy->GetStringWithoutPathExpansion(
677           shill::kDeviceProperty, &device_path) ||
678       device_path.empty()) {
679     send_callback.Run(service_path, shill_properties_copy.Pass());
680     return;
681   }
682 
683   // Request the device properties. On success or failure pass (a possibly
684   // modified) |shill_properties| to |send_callback|.
685   scoped_ptr<base::DictionaryValue> shill_properties_copy_error_copy(
686       shill_properties_copy->DeepCopy());
687   network_device_handler_->GetDeviceProperties(
688       device_path,
689       base::Bind(&ManagedNetworkConfigurationHandlerImpl::
690                      GetDevicePropertiesSuccess,
691                  weak_ptr_factory_.GetWeakPtr(),
692                  service_path,
693                  base::Passed(&shill_properties_copy),
694                  send_callback),
695       base::Bind(&ManagedNetworkConfigurationHandlerImpl::
696                      GetDevicePropertiesFailure,
697                  weak_ptr_factory_.GetWeakPtr(),
698                  service_path,
699                  base::Passed(&shill_properties_copy_error_copy),
700                  send_callback));
701 }
702 
GetDevicePropertiesSuccess(const std::string & service_path,scoped_ptr<base::DictionaryValue> network_properties,GetDevicePropertiesCallback send_callback,const std::string & device_path,const base::DictionaryValue & device_properties)703 void ManagedNetworkConfigurationHandlerImpl::GetDevicePropertiesSuccess(
704     const std::string& service_path,
705     scoped_ptr<base::DictionaryValue> network_properties,
706     GetDevicePropertiesCallback send_callback,
707     const std::string& device_path,
708     const base::DictionaryValue& device_properties) {
709   // Create a "Device" dictionary in |network_properties|.
710   network_properties->SetWithoutPathExpansion(
711       shill::kDeviceProperty, device_properties.DeepCopy());
712   send_callback.Run(service_path, network_properties.Pass());
713 }
714 
GetDevicePropertiesFailure(const std::string & service_path,scoped_ptr<base::DictionaryValue> network_properties,GetDevicePropertiesCallback send_callback,const std::string & error_name,scoped_ptr<base::DictionaryValue> error_data)715 void ManagedNetworkConfigurationHandlerImpl::GetDevicePropertiesFailure(
716     const std::string& service_path,
717     scoped_ptr<base::DictionaryValue> network_properties,
718     GetDevicePropertiesCallback send_callback,
719     const std::string& error_name,
720     scoped_ptr<base::DictionaryValue> error_data) {
721   NET_LOG_ERROR("Error getting device properties", service_path);
722   send_callback.Run(service_path, network_properties.Pass());
723 }
724 
725 
726 }  // namespace chromeos
727