Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chromeos / network / managed_network_configuration_handler_impl.cc
blobc92e7f60adcbb49bec5dca9934580ef3cb701d23
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.
5 #include "chromeos/network/managed_network_configuration_handler_impl.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/guid.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/stl_util.h"
16 #include "base/values.h"
17 #include "chromeos/dbus/shill_manager_client.h"
18 #include "chromeos/dbus/shill_profile_client.h"
19 #include "chromeos/dbus/shill_service_client.h"
20 #include "chromeos/network/device_state.h"
21 #include "chromeos/network/network_configuration_handler.h"
22 #include "chromeos/network/network_device_handler.h"
23 #include "chromeos/network/network_event_log.h"
24 #include "chromeos/network/network_policy_observer.h"
25 #include "chromeos/network/network_profile.h"
26 #include "chromeos/network/network_profile_handler.h"
27 #include "chromeos/network/network_state.h"
28 #include "chromeos/network/network_state_handler.h"
29 #include "chromeos/network/network_ui_data.h"
30 #include "chromeos/network/network_util.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_utils.h"
35 #include "chromeos/network/onc/onc_validator.h"
36 #include "chromeos/network/policy_util.h"
37 #include "chromeos/network/shill_property_util.h"
38 #include "components/onc/onc_constants.h"
39 #include "third_party/cros_system_api/dbus/service_constants.h"
41 namespace chromeos {
43 namespace {
45 using GuidToPolicyMap = ManagedNetworkConfigurationHandler::GuidToPolicyMap;
47 // These are error strings used for error callbacks. None of these error
48 // messages are user-facing: they should only appear in logs.
49 const char kInvalidUserSettings[] = "InvalidUserSettings";
50 const char kNetworkAlreadyConfigured[] = "NetworkAlreadyConfigured";
51 const char kPoliciesNotInitialized[] = "PoliciesNotInitialized";
52 const char kProfileNotInitialized[] = "ProfileNotInitialized";
53 const char kUnconfiguredNetwork[] = "UnconfiguredNetwork";
54 const char kUnknownNetwork[] = "UnknownNetwork";
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";
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);
71 void LogErrorWithDict(const tracked_objects::Location& from_where,
72 const std::string& error_name,
73 scoped_ptr<base::DictionaryValue> error_data) {
74 device_event_log::AddEntry(from_where.file_name(), from_where.line_number(),
75 device_event_log::LOG_TYPE_NETWORK,
76 device_event_log::LOG_LEVEL_ERROR, error_name);
79 const base::DictionaryValue* GetByGUID(const GuidToPolicyMap& policies,
80 const std::string& guid) {
81 GuidToPolicyMap::const_iterator it = policies.find(guid);
82 if (it == policies.end())
83 return NULL;
84 return it->second;
87 } // namespace
89 struct ManagedNetworkConfigurationHandlerImpl::Policies {
90 ~Policies();
92 GuidToPolicyMap per_network_config;
93 base::DictionaryValue global_network_config;
96 ManagedNetworkConfigurationHandlerImpl::Policies::~Policies() {
97 STLDeleteValues(&per_network_config);
100 void ManagedNetworkConfigurationHandlerImpl::AddObserver(
101 NetworkPolicyObserver* observer) {
102 observers_.AddObserver(observer);
105 void ManagedNetworkConfigurationHandlerImpl::RemoveObserver(
106 NetworkPolicyObserver* observer) {
107 observers_.RemoveObserver(observer);
110 // GetManagedProperties
112 void ManagedNetworkConfigurationHandlerImpl::GetManagedProperties(
113 const std::string& userhash,
114 const std::string& service_path,
115 const network_handler::DictionaryResultCallback& callback,
116 const network_handler::ErrorCallback& error_callback) {
117 if (!GetPoliciesForUser(userhash) || !GetPoliciesForUser(std::string())) {
118 InvokeErrorCallback(service_path, error_callback, kPoliciesNotInitialized);
119 return;
121 NET_LOG_USER("GetManagedProperties", service_path);
122 network_configuration_handler_->GetShillProperties(
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(), userhash, callback,
130 error_callback)),
131 error_callback);
134 void ManagedNetworkConfigurationHandlerImpl::SendManagedProperties(
135 const std::string& userhash,
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);
148 scoped_ptr<NetworkUIData> ui_data =
149 shill_property_util::GetUIDataFromProperties(*shill_properties);
151 const base::DictionaryValue* user_settings = NULL;
153 if (ui_data && profile) {
154 user_settings = ui_data->user_settings();
155 } else if (profile) {
156 NET_LOG_ERROR("Service contains empty or invalid UIData", service_path);
157 // TODO(pneubeck): add a conversion of user configured entries of old
158 // ChromeOS versions. We will have to use a heuristic to determine which
159 // properties _might_ be user configured.
162 std::string guid;
163 shill_properties->GetStringWithoutPathExpansion(shill::kGuidProperty, &guid);
165 ::onc::ONCSource onc_source;
166 FindPolicyByGUID(userhash, guid, &onc_source);
167 const NetworkState* network_state =
168 network_state_handler_->GetNetworkState(service_path);
169 scoped_ptr<base::DictionaryValue> active_settings(
170 onc::TranslateShillServiceToONCPart(*shill_properties, onc_source,
171 &onc::kNetworkWithStateSignature,
172 network_state));
174 const base::DictionaryValue* network_policy = NULL;
175 const base::DictionaryValue* global_policy = NULL;
176 if (profile) {
177 const Policies* policies = GetPoliciesForProfile(*profile);
178 if (!policies) {
179 InvokeErrorCallback(
180 service_path, error_callback, kPoliciesNotInitialized);
181 return;
183 if (!guid.empty())
184 network_policy = GetByGUID(policies->per_network_config, guid);
185 global_policy = &policies->global_network_config;
188 scoped_ptr<base::DictionaryValue> augmented_properties(
189 policy_util::CreateManagedONC(global_policy,
190 network_policy,
191 user_settings,
192 active_settings.get(),
193 profile));
194 callback.Run(service_path, *augmented_properties);
197 // GetProperties
199 void ManagedNetworkConfigurationHandlerImpl::GetProperties(
200 const std::string& userhash,
201 const std::string& service_path,
202 const network_handler::DictionaryResultCallback& callback,
203 const network_handler::ErrorCallback& error_callback) {
204 NET_LOG_USER("GetProperties", service_path);
205 network_configuration_handler_->GetShillProperties(
206 service_path,
207 base::Bind(
208 &ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback,
209 weak_ptr_factory_.GetWeakPtr(),
210 base::Bind(&ManagedNetworkConfigurationHandlerImpl::SendProperties,
211 weak_ptr_factory_.GetWeakPtr(), userhash, callback,
212 error_callback)),
213 error_callback);
216 void ManagedNetworkConfigurationHandlerImpl::SendProperties(
217 const std::string& userhash,
218 const network_handler::DictionaryResultCallback& callback,
219 const network_handler::ErrorCallback& error_callback,
220 const std::string& service_path,
221 scoped_ptr<base::DictionaryValue> shill_properties) {
222 const NetworkState* network_state =
223 network_state_handler_->GetNetworkState(service_path);
225 std::string guid;
226 shill_properties->GetStringWithoutPathExpansion(shill::kGuidProperty, &guid);
228 ::onc::ONCSource onc_source;
229 FindPolicyByGUID(userhash, guid, &onc_source);
231 scoped_ptr<base::DictionaryValue> onc_network(
232 onc::TranslateShillServiceToONCPart(*shill_properties, onc_source,
233 &onc::kNetworkWithStateSignature,
234 network_state));
235 callback.Run(service_path, *onc_network);
238 // SetProperties
240 void ManagedNetworkConfigurationHandlerImpl::SetProperties(
241 const std::string& service_path,
242 const base::DictionaryValue& user_settings,
243 const base::Closure& callback,
244 const network_handler::ErrorCallback& error_callback) {
245 const NetworkState* state =
246 network_state_handler_->GetNetworkStateFromServicePath(
247 service_path, true /* configured_only */);
248 if (!state) {
249 InvokeErrorCallback(service_path, error_callback, kUnknownNetwork);
250 return;
253 std::string guid = state->guid();
254 DCHECK(!guid.empty());
256 const std::string& profile_path = state->profile_path();
257 const NetworkProfile *profile =
258 network_profile_handler_->GetProfileForPath(profile_path);
259 if (!profile) {
260 // TODO(pneubeck): create an initial configuration in this case. As for
261 // CreateConfiguration, user settings from older ChromeOS versions have to
262 // be determined here.
263 InvokeErrorCallback(service_path, error_callback, kUnconfiguredNetwork);
264 return;
267 VLOG(2) << "SetProperties: Found GUID " << guid << " and profile "
268 << profile->ToDebugString();
270 const Policies* policies = GetPoliciesForProfile(*profile);
271 if (!policies) {
272 InvokeErrorCallback(service_path, error_callback, kPoliciesNotInitialized);
273 return;
276 // We need to ensure that required configuration properties (e.g. Type) are
277 // included for ONC validation and translation to Shill properties.
278 scoped_ptr<base::DictionaryValue> user_settings_copy(
279 user_settings.DeepCopy());
280 user_settings_copy->SetStringWithoutPathExpansion(
281 ::onc::network_config::kType,
282 network_util::TranslateShillTypeToONC(state->type()));
283 user_settings_copy->MergeDictionary(&user_settings);
285 // Validate the ONC dictionary. We are liberal and ignore unknown field
286 // names. User settings are only partial ONC, thus we ignore missing fields.
287 onc::Validator validator(false, // Ignore unknown fields.
288 false, // Ignore invalid recommended field names.
289 false, // Ignore missing fields.
290 false); // This ONC does not come from policy.
292 onc::Validator::Result validation_result;
293 scoped_ptr<base::DictionaryValue> validated_user_settings =
294 validator.ValidateAndRepairObject(
295 &onc::kNetworkConfigurationSignature,
296 *user_settings_copy,
297 &validation_result);
298 if (validation_result == onc::Validator::INVALID) {
299 InvokeErrorCallback(service_path, error_callback, kInvalidUserSettings);
300 return;
302 if (validation_result == onc::Validator::VALID_WITH_WARNINGS)
303 LOG(WARNING) << "Validation of ONC user settings produced warnings.";
305 // Fill in HexSSID field from contents of SSID field if not set already.
306 if (user_settings_copy) {
307 onc::FillInHexSSIDFieldsInOncObject(onc::kNetworkConfigurationSignature,
308 validated_user_settings.get());
311 const base::DictionaryValue* network_policy =
312 GetByGUID(policies->per_network_config, guid);
313 VLOG(2) << "This configuration is " << (network_policy ? "" : "not ")
314 << "managed.";
316 scoped_ptr<base::DictionaryValue> shill_dictionary(
317 policy_util::CreateShillConfiguration(*profile,
318 guid,
319 &policies->global_network_config,
320 network_policy,
321 validated_user_settings.get()));
323 // 'Carrier' needs to be handled specially if set.
324 base::DictionaryValue* cellular = nullptr;
325 if (validated_user_settings->GetDictionaryWithoutPathExpansion(
326 ::onc::network_config::kCellular, &cellular)) {
327 std::string carrier;
328 if (cellular->GetStringWithoutPathExpansion(::onc::cellular::kCarrier,
329 &carrier)) {
330 network_device_handler_->SetCarrier(
331 state->device_path(), carrier,
332 base::Bind(
333 &ManagedNetworkConfigurationHandlerImpl::SetShillProperties,
334 weak_ptr_factory_.GetWeakPtr(), service_path,
335 base::Passed(&shill_dictionary), callback, error_callback),
336 error_callback);
337 return;
341 SetShillProperties(service_path, shill_dictionary.Pass(), callback,
342 error_callback);
345 void ManagedNetworkConfigurationHandlerImpl::SetShillProperties(
346 const std::string& service_path,
347 scoped_ptr<base::DictionaryValue> shill_dictionary,
348 const base::Closure& callback,
349 const network_handler::ErrorCallback& error_callback) {
350 network_configuration_handler_->SetShillProperties(
351 service_path, *shill_dictionary,
352 NetworkConfigurationObserver::SOURCE_USER_ACTION, callback,
353 error_callback);
356 void ManagedNetworkConfigurationHandlerImpl::CreateConfiguration(
357 const std::string& userhash,
358 const base::DictionaryValue& properties,
359 const network_handler::StringResultCallback& callback,
360 const network_handler::ErrorCallback& error_callback) const {
361 const Policies* policies = GetPoliciesForUser(userhash);
362 if (!policies) {
363 InvokeErrorCallback("", error_callback, kPoliciesNotInitialized);
364 return;
367 if (policy_util::FindMatchingPolicy(policies->per_network_config,
368 properties)) {
369 InvokeErrorCallback("", error_callback, kNetworkAlreadyConfigured);
370 return;
373 const NetworkProfile* profile =
374 network_profile_handler_->GetProfileForUserhash(userhash);
375 if (!profile) {
376 InvokeErrorCallback("", error_callback, kProfileNotInitialized);
377 return;
380 // TODO(pneubeck): In case of WiFi, check that no other configuration for the
381 // same {SSID, mode, security} exists. We don't support such multiple
382 // configurations, yet.
384 // Generate a new GUID for this configuration. Ignore the maybe provided GUID
385 // in |properties| as it is not our own and from an untrusted source.
386 std::string guid = base::GenerateGUID();
387 scoped_ptr<base::DictionaryValue> shill_dictionary(
388 policy_util::CreateShillConfiguration(*profile,
389 guid,
390 NULL, // no global policy
391 NULL, // no network policy
392 &properties));
394 network_configuration_handler_->CreateShillConfiguration(
395 *shill_dictionary, NetworkConfigurationObserver::SOURCE_USER_ACTION,
396 callback, error_callback);
399 void ManagedNetworkConfigurationHandlerImpl::RemoveConfiguration(
400 const std::string& service_path,
401 const base::Closure& callback,
402 const network_handler::ErrorCallback& error_callback) const {
403 network_configuration_handler_->RemoveConfiguration(
404 service_path, NetworkConfigurationObserver::SOURCE_USER_ACTION, callback,
405 error_callback);
408 void ManagedNetworkConfigurationHandlerImpl::SetPolicy(
409 ::onc::ONCSource onc_source,
410 const std::string& userhash,
411 const base::ListValue& network_configs_onc,
412 const base::DictionaryValue& global_network_config) {
413 VLOG(1) << "Setting policies from " << ToDebugString(onc_source, userhash)
414 << ".";
416 // |userhash| must be empty for device policies.
417 DCHECK(onc_source != ::onc::ONC_SOURCE_DEVICE_POLICY ||
418 userhash.empty());
419 Policies* policies = NULL;
420 if (ContainsKey(policies_by_user_, userhash)) {
421 policies = policies_by_user_[userhash].get();
422 } else {
423 policies = new Policies;
424 policies_by_user_[userhash] = make_linked_ptr(policies);
427 policies->global_network_config.MergeDictionary(&global_network_config);
429 GuidToPolicyMap old_per_network_config;
430 policies->per_network_config.swap(old_per_network_config);
432 // This stores all GUIDs of policies that have changed or are new.
433 std::set<std::string> modified_policies;
435 for (base::ListValue::const_iterator it = network_configs_onc.begin();
436 it != network_configs_onc.end(); ++it) {
437 const base::DictionaryValue* network = NULL;
438 (*it)->GetAsDictionary(&network);
439 DCHECK(network);
441 std::string guid;
442 network->GetStringWithoutPathExpansion(::onc::network_config::kGUID, &guid);
443 DCHECK(!guid.empty());
445 if (policies->per_network_config.count(guid) > 0) {
446 NET_LOG_ERROR("ONC from " + ToDebugString(onc_source, userhash) +
447 " contains several entries for the same GUID ", guid);
448 delete policies->per_network_config[guid];
450 const base::DictionaryValue* new_entry = network->DeepCopy();
451 policies->per_network_config[guid] = new_entry;
453 const base::DictionaryValue* old_entry = old_per_network_config[guid];
454 if (!old_entry || !old_entry->Equals(new_entry))
455 modified_policies.insert(guid);
458 STLDeleteValues(&old_per_network_config);
459 ApplyOrQueuePolicies(userhash, &modified_policies);
460 FOR_EACH_OBSERVER(NetworkPolicyObserver, observers_,
461 PoliciesChanged(userhash));
464 bool ManagedNetworkConfigurationHandlerImpl::IsAnyPolicyApplicationRunning()
465 const {
466 return !policy_applicators_.empty() || !queued_modified_policies_.empty();
469 bool ManagedNetworkConfigurationHandlerImpl::ApplyOrQueuePolicies(
470 const std::string& userhash,
471 std::set<std::string>* modified_policies) {
472 DCHECK(modified_policies);
474 const NetworkProfile* profile =
475 network_profile_handler_->GetProfileForUserhash(userhash);
476 if (!profile) {
477 VLOG(1) << "The relevant Shill profile isn't initialized yet, postponing "
478 << "policy application.";
479 // OnProfileAdded will apply all policies for this userhash.
480 return false;
483 if (ContainsKey(policy_applicators_, userhash)) {
484 // A previous policy application is still running. Queue the modified
485 // policies.
486 // Note, even if |modified_policies| is empty, this means that a policy
487 // application will be queued.
488 queued_modified_policies_[userhash].insert(modified_policies->begin(),
489 modified_policies->end());
490 VLOG(1) << "Previous PolicyApplicator still running. Postponing policy "
491 "application.";
492 return false;
495 const Policies* policies = policies_by_user_[userhash].get();
496 DCHECK(policies);
498 PolicyApplicator* applicator =
499 new PolicyApplicator(*profile,
500 policies->per_network_config,
501 policies->global_network_config,
502 this,
503 modified_policies);
504 policy_applicators_[userhash] = make_linked_ptr(applicator);
505 applicator->Run();
506 return true;
509 void ManagedNetworkConfigurationHandlerImpl::OnProfileAdded(
510 const NetworkProfile& profile) {
511 VLOG(1) << "Adding profile " << profile.ToDebugString() << "'.";
513 const Policies* policies = GetPoliciesForProfile(profile);
514 if (!policies) {
515 VLOG(1) << "The relevant policy is not initialized, "
516 << "postponing policy application.";
517 // See SetPolicy.
518 return;
521 std::set<std::string> policy_guids;
522 for (GuidToPolicyMap::const_iterator it =
523 policies->per_network_config.begin();
524 it != policies->per_network_config.end(); ++it) {
525 policy_guids.insert(it->first);
528 const bool started_policy_application =
529 ApplyOrQueuePolicies(profile.userhash, &policy_guids);
530 DCHECK(started_policy_application);
533 void ManagedNetworkConfigurationHandlerImpl::OnProfileRemoved(
534 const NetworkProfile& profile) {
535 // Nothing to do in this case.
538 void ManagedNetworkConfigurationHandlerImpl::CreateConfigurationFromPolicy(
539 const base::DictionaryValue& shill_properties) {
540 network_configuration_handler_->CreateShillConfiguration(
541 shill_properties, NetworkConfigurationObserver::SOURCE_POLICY,
542 base::Bind(
543 &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork,
544 weak_ptr_factory_.GetWeakPtr()),
545 base::Bind(&LogErrorWithDict, FROM_HERE));
548 void ManagedNetworkConfigurationHandlerImpl::
549 UpdateExistingConfigurationWithPropertiesFromPolicy(
550 const base::DictionaryValue& existing_properties,
551 const base::DictionaryValue& new_properties) {
552 base::DictionaryValue shill_properties;
554 std::string profile;
555 existing_properties.GetStringWithoutPathExpansion(shill::kProfileProperty,
556 &profile);
557 if (profile.empty()) {
558 NET_LOG_ERROR("Missing profile property",
559 shill_property_util::GetNetworkIdFromProperties(
560 existing_properties));
561 return;
563 shill_properties.SetStringWithoutPathExpansion(shill::kProfileProperty,
564 profile);
566 if (!shill_property_util::CopyIdentifyingProperties(
567 existing_properties,
568 true /* properties were read from Shill */,
569 &shill_properties)) {
570 NET_LOG_ERROR("Missing identifying properties",
571 shill_property_util::GetNetworkIdFromProperties(
572 existing_properties));
575 shill_properties.MergeDictionary(&new_properties);
577 network_configuration_handler_->CreateShillConfiguration(
578 shill_properties, NetworkConfigurationObserver::SOURCE_POLICY,
579 base::Bind(
580 &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork,
581 weak_ptr_factory_.GetWeakPtr()),
582 base::Bind(&LogErrorWithDict, FROM_HERE));
585 void ManagedNetworkConfigurationHandlerImpl::OnPoliciesApplied(
586 const NetworkProfile& profile) {
587 const std::string& userhash = profile.userhash;
588 VLOG(1) << "Policy application for user '" << userhash << "' finished.";
590 base::MessageLoop::current()->DeleteSoon(
591 FROM_HERE, policy_applicators_[userhash].release());
592 policy_applicators_.erase(userhash);
594 if (ContainsKey(queued_modified_policies_, userhash)) {
595 std::set<std::string> modified_policies;
596 queued_modified_policies_[userhash].swap(modified_policies);
597 // Remove |userhash| from the queue.
598 queued_modified_policies_.erase(userhash);
599 ApplyOrQueuePolicies(userhash, &modified_policies);
600 } else {
601 FOR_EACH_OBSERVER(
602 NetworkPolicyObserver, observers_, PoliciesApplied(userhash));
606 const base::DictionaryValue*
607 ManagedNetworkConfigurationHandlerImpl::FindPolicyByGUID(
608 const std::string userhash,
609 const std::string& guid,
610 ::onc::ONCSource* onc_source) const {
611 *onc_source = ::onc::ONC_SOURCE_NONE;
613 if (!userhash.empty()) {
614 const Policies* user_policies = GetPoliciesForUser(userhash);
615 if (user_policies) {
616 const base::DictionaryValue* policy =
617 GetByGUID(user_policies->per_network_config, guid);
618 if (policy) {
619 *onc_source = ::onc::ONC_SOURCE_USER_POLICY;
620 return policy;
625 const Policies* device_policies = GetPoliciesForUser(std::string());
626 if (device_policies) {
627 const base::DictionaryValue* policy =
628 GetByGUID(device_policies->per_network_config, guid);
629 if (policy) {
630 *onc_source = ::onc::ONC_SOURCE_DEVICE_POLICY;
631 return policy;
635 return NULL;
638 const GuidToPolicyMap*
639 ManagedNetworkConfigurationHandlerImpl::GetNetworkConfigsFromPolicy(
640 const std::string& userhash) const {
641 const Policies* policies = GetPoliciesForUser(userhash);
642 if (!policies)
643 return NULL;
645 return &policies->per_network_config;
648 const base::DictionaryValue*
649 ManagedNetworkConfigurationHandlerImpl::GetGlobalConfigFromPolicy(
650 const std::string& userhash) const {
651 const Policies* policies = GetPoliciesForUser(userhash);
652 if (!policies)
653 return NULL;
655 return &policies->global_network_config;
658 const base::DictionaryValue*
659 ManagedNetworkConfigurationHandlerImpl::FindPolicyByGuidAndProfile(
660 const std::string& guid,
661 const std::string& profile_path) const {
662 const NetworkProfile* profile =
663 network_profile_handler_->GetProfileForPath(profile_path);
664 if (!profile) {
665 NET_LOG_ERROR("Profile path unknown:" + profile_path, guid);
666 return NULL;
669 const Policies* policies = GetPoliciesForProfile(*profile);
670 if (!policies)
671 return NULL;
673 return GetByGUID(policies->per_network_config, guid);
676 const ManagedNetworkConfigurationHandlerImpl::Policies*
677 ManagedNetworkConfigurationHandlerImpl::GetPoliciesForUser(
678 const std::string& userhash) const {
679 UserToPoliciesMap::const_iterator it = policies_by_user_.find(userhash);
680 if (it == policies_by_user_.end())
681 return NULL;
682 return it->second.get();
685 const ManagedNetworkConfigurationHandlerImpl::Policies*
686 ManagedNetworkConfigurationHandlerImpl::GetPoliciesForProfile(
687 const NetworkProfile& profile) const {
688 DCHECK(profile.type() != NetworkProfile::TYPE_SHARED ||
689 profile.userhash.empty());
690 return GetPoliciesForUser(profile.userhash);
693 ManagedNetworkConfigurationHandlerImpl::ManagedNetworkConfigurationHandlerImpl()
694 : network_state_handler_(NULL),
695 network_profile_handler_(NULL),
696 network_configuration_handler_(NULL),
697 network_device_handler_(NULL),
698 weak_ptr_factory_(this) {
699 CHECK(base::MessageLoop::current());
702 ManagedNetworkConfigurationHandlerImpl::
703 ~ManagedNetworkConfigurationHandlerImpl() {
704 if (network_profile_handler_)
705 network_profile_handler_->RemoveObserver(this);
708 void ManagedNetworkConfigurationHandlerImpl::Init(
709 NetworkStateHandler* network_state_handler,
710 NetworkProfileHandler* network_profile_handler,
711 NetworkConfigurationHandler* network_configuration_handler,
712 NetworkDeviceHandler* network_device_handler) {
713 network_state_handler_ = network_state_handler;
714 network_profile_handler_ = network_profile_handler;
715 network_configuration_handler_ = network_configuration_handler;
716 network_device_handler_ = network_device_handler;
717 network_profile_handler_->AddObserver(this);
720 void ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork(
721 const std::string& service_path) {
722 if (service_path.empty())
723 return;
724 FOR_EACH_OBSERVER(
725 NetworkPolicyObserver, observers_, PolicyAppliedToNetwork(service_path));
728 // Get{Managed}Properties helpers
730 void ManagedNetworkConfigurationHandlerImpl::GetDeviceStateProperties(
731 const std::string& service_path,
732 base::DictionaryValue* properties) {
733 std::string connection_state;
734 properties->GetStringWithoutPathExpansion(
735 shill::kStateProperty, &connection_state);
736 if (!NetworkState::StateIsConnected(connection_state))
737 return;
739 // Get the IPConfig properties from the device and store them in "IPConfigs"
740 // (plural) in the properties dictionary. (Note: Shill only provides a single
741 // "IPConfig" property for a network service, but a consumer of this API may
742 // want information about all ipv4 and ipv6 IPConfig properties.
743 std::string device;
744 properties->GetStringWithoutPathExpansion(shill::kDeviceProperty, &device);
745 const DeviceState* device_state =
746 network_state_handler_->GetDeviceState(device);
747 if (!device_state) {
748 NET_LOG_ERROR("GetDeviceProperties: no device: " + device, service_path);
749 return;
752 // Get the hardware MAC address from the DeviceState.
753 if (!device_state->mac_address().empty()) {
754 properties->SetStringWithoutPathExpansion(
755 shill::kAddressProperty, device_state->mac_address());
758 // Convert IPConfig dictionary to a ListValue.
759 base::ListValue* ip_configs = new base::ListValue;
760 for (base::DictionaryValue::Iterator iter(device_state->ip_configs());
761 !iter.IsAtEnd(); iter.Advance()) {
762 ip_configs->Append(iter.value().DeepCopy());
764 properties->SetWithoutPathExpansion(shill::kIPConfigsProperty, ip_configs);
767 void ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback(
768 GetDevicePropertiesCallback send_callback,
769 const std::string& service_path,
770 const base::DictionaryValue& shill_properties) {
771 scoped_ptr<base::DictionaryValue> shill_properties_copy(
772 shill_properties.DeepCopy());
774 std::string guid;
775 shill_properties.GetStringWithoutPathExpansion(shill::kGuidProperty, &guid);
776 if (guid.empty()) {
777 // Unmanaged networks are assigned a GUID in NetworkState. Provide this
778 // value in the ONC dictionary.
779 const NetworkState* state =
780 network_state_handler_->GetNetworkState(service_path);
781 if (state && !state->guid().empty()) {
782 guid = state->guid();
783 shill_properties_copy->SetStringWithoutPathExpansion(shill::kGuidProperty,
784 guid);
785 } else {
786 LOG(ERROR) << "Network has no GUID specified: " << service_path;
790 std::string type;
791 shill_properties_copy->GetStringWithoutPathExpansion(shill::kTypeProperty,
792 &type);
793 // Add associated DeviceState properties for non-VPN networks.
794 if (type != shill::kTypeVPN)
795 GetDeviceStateProperties(service_path, shill_properties_copy.get());
797 // Only request additional Device properties for Cellular networks with a
798 // valid device.
799 std::string device_path;
800 if (!network_device_handler_ ||
801 type != shill::kTypeCellular ||
802 !shill_properties_copy->GetStringWithoutPathExpansion(
803 shill::kDeviceProperty, &device_path) ||
804 device_path.empty()) {
805 send_callback.Run(service_path, shill_properties_copy.Pass());
806 return;
809 // Request the device properties. On success or failure pass (a possibly
810 // modified) |shill_properties| to |send_callback|.
811 scoped_ptr<base::DictionaryValue> shill_properties_copy_error_copy(
812 shill_properties_copy->DeepCopy());
813 network_device_handler_->GetDeviceProperties(
814 device_path,
815 base::Bind(&ManagedNetworkConfigurationHandlerImpl::
816 GetDevicePropertiesSuccess,
817 weak_ptr_factory_.GetWeakPtr(),
818 service_path,
819 base::Passed(&shill_properties_copy),
820 send_callback),
821 base::Bind(&ManagedNetworkConfigurationHandlerImpl::
822 GetDevicePropertiesFailure,
823 weak_ptr_factory_.GetWeakPtr(),
824 service_path,
825 base::Passed(&shill_properties_copy_error_copy),
826 send_callback));
829 void ManagedNetworkConfigurationHandlerImpl::GetDevicePropertiesSuccess(
830 const std::string& service_path,
831 scoped_ptr<base::DictionaryValue> network_properties,
832 GetDevicePropertiesCallback send_callback,
833 const std::string& device_path,
834 const base::DictionaryValue& device_properties) {
835 // Create a "Device" dictionary in |network_properties|.
836 network_properties->SetWithoutPathExpansion(
837 shill::kDeviceProperty, device_properties.DeepCopy());
838 send_callback.Run(service_path, network_properties.Pass());
841 void ManagedNetworkConfigurationHandlerImpl::GetDevicePropertiesFailure(
842 const std::string& service_path,
843 scoped_ptr<base::DictionaryValue> network_properties,
844 GetDevicePropertiesCallback send_callback,
845 const std::string& error_name,
846 scoped_ptr<base::DictionaryValue> error_data) {
847 NET_LOG_ERROR("Error getting device properties", service_path);
848 send_callback.Run(service_path, network_properties.Pass());
852 } // namespace chromeos