Index: components/wifi_sync/wifi_config_observer_chromeos.cc |
diff --git a/components/wifi_sync/wifi_config_observer_chromeos.cc b/components/wifi_sync/wifi_config_observer_chromeos.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0b903c5ac0ca7e19ddd01b03495909c63770aea8 |
--- /dev/null |
+++ b/components/wifi_sync/wifi_config_observer_chromeos.cc |
@@ -0,0 +1,235 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "components/wifi_sync/wifi_config_observer_chromeos.h" |
+ |
+#include "base/location.h" |
+#include "base/logging.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/values.h" |
+#include "chromeos/network/managed_network_configuration_handler.h" |
+#include "chromeos/network/network_configuration_handler.h" |
+#include "chromeos/network/network_state.h" |
+#include "chromeos/network/network_state_handler.h" |
+#include "components/wifi_sync/wifi_credential.h" |
+#include "components/wifi_sync/wifi_credential_syncable_service.h" |
+#include "components/wifi_sync/wifi_security_class.h" |
+#include "third_party/cros_system_api/dbus/service_constants.h" |
+ |
+namespace wifi_sync { |
+ |
+WifiConfigObserverChromeOs::WifiConfigObserverChromeOs( |
+ const std::string& user_hash, |
+ chromeos::ManagedNetworkConfigurationHandler* managed_net_config_handler, |
+ chromeos::NetworkConfigurationHandler* network_configuration_handler, |
+ chromeos::NetworkStateHandler* network_state_handler) |
+ : user_hash_(user_hash), |
+ managed_network_configuration_handler_(managed_net_config_handler), |
+ network_configuration_handler_(network_configuration_handler), |
+ network_state_handler_(network_state_handler) { |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ DCHECK(managed_network_configuration_handler_); |
+ DCHECK(network_configuration_handler_); |
+ DCHECK(network_state_handler_); |
+ network_configuration_handler_->AddObserver(this); |
+ network_state_handler_->AddObserver(this, FROM_HERE); |
+} |
+ |
+WifiConfigObserverChromeOs::~WifiConfigObserverChromeOs() { |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ for (const WifiCredential& credential |
+ : credentials_awaiting_syncable_service_) { |
+ // TODO(quiche): Report event to UMA. |
+ LOG(WARNING) << "No syncable_service_; did not sync " |
+ << credential.ToString(); |
+ } |
+ |
+ network_state_handler_->RemoveObserver(this, FROM_HERE); |
+ network_configuration_handler_->RemoveObserver(this); |
+} |
+ |
+void WifiConfigObserverChromeOs::StartSyncing( |
+ base::WeakPtr<WifiCredentialSyncableService> syncable_service) { |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ DCHECK(syncable_service); |
+ DCHECK(!syncable_service_); |
+ syncable_service_ = syncable_service; |
+ for (const WifiCredential& credential |
+ : credentials_awaiting_syncable_service_) |
+ syncable_service_->AddToSyncedNetworks(credential); |
+ credentials_awaiting_syncable_service_.clear(); |
+} |
+ |
+void WifiConfigObserverChromeOs::StopSyncing() { |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ syncable_service_.reset(); |
+} |
+ |
+// Note: This function is not called when a network is created from |
+// scan results. We handle such networks via OnPropertiesSet and/or |
+// OnConfigurationProfileChanged. |
+void WifiConfigObserverChromeOs::OnConfigurationCreated( |
+ const std::string& service_path, |
+ const std::string& profile_path, |
+ const base::DictionaryValue& properties, |
+ NetworkConfigurationObserver::Source source) { |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ std::string guid; |
+ if (!properties.GetStringWithoutPathExpansion(shill::kGuidProperty, &guid)) { |
+ LOG(ERROR) << "Failed to read GUID for " << service_path; |
+ return; |
+ } |
+ ProcessProperties(guid, properties, source); |
+} |
+ |
+void WifiConfigObserverChromeOs::OnConfigurationRemoved( |
+ const std::string& service_path, |
+ const std::string& guid, |
+ NetworkConfigurationObserver::Source source) { |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ if (source != SOURCE_USER_ACTION) |
+ return; |
+ // TODO(quiche): send this up to |syncable_service|. crbug.com/431439 |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void WifiConfigObserverChromeOs::OnPropertiesSet( |
+ const std::string& service_path, |
+ const std::string& guid, |
+ const base::DictionaryValue& set_properties, |
+ NetworkConfigurationObserver::Source source) { |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ ProcessProperties(guid, set_properties, source); |
+} |
+ |
+// XXX may happen after NetworkConnectionStateChanged |
+void WifiConfigObserverChromeOs::OnConfigurationProfileChanged( |
+ const std::string& service_path, |
+ const std::string& profile_path, |
+ NetworkConfigurationObserver::Source source) { |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ // TODO(quiche): Consider removing this network from sync, if the |
+ // new profile is not the user's profile, and is not the default |
+ // profile. |
+ // XXX need |source| check |
+ const chromeos::NetworkState* network = |
+ network_state_handler_->GetNetworkState(service_path); |
+ if (!network) { |
+ LOG(ERROR) << "Failed to get NetworkState for " << service_path; |
+ return; |
+ } |
+ user_configured_service_guids_.insert(network->guid()); |
+ TryToSyncNetwork(network); |
+} |
+ |
+void WifiConfigObserverChromeOs::NetworkConnectionStateChanged( |
+ const chromeos::NetworkState* network) { |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ DCHECK(network); |
+ |
+ if (user_configured_service_guids_.find(network->guid()) == |
+ user_configured_service_guids_.end()) |
+ return; |
+ |
+ TryToSyncNetwork(network); |
+} |
+ |
+// Private methods. |
+ |
+void WifiConfigObserverChromeOs::ProcessProperties( |
+ const std::string& guid, |
+ const base::DictionaryValue& service_properties, |
+ NetworkConfigurationObserver::Source source) { |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ if (source != SOURCE_USER_ACTION) { |
+ // XXX Determine if we need to filter this for only |
+ // passphrase changes. We would need to do so if, e.g., we get a |
+ // OnPropertiesSet call for MNCH auto-generating a GUID. |
+ user_configured_service_guids_.erase(guid); |
+ guid_to_passphrase_.erase(guid); |
+ return; |
+ } |
+ user_configured_service_guids_.insert(guid); |
+ SavePassphraseForService(guid, service_properties); |
+} |
+ |
+void WifiConfigObserverChromeOs::SavePassphraseForService( |
+ const std::string& guid, |
+ const base::DictionaryValue& service_properties) { |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ if (!service_properties.HasKey(shill::kPassphraseProperty)) |
+ return; |
+ |
+ std::string passphrase; |
+ if (!service_properties.GetStringWithoutPathExpansion( |
+ shill::kPassphraseProperty, &passphrase)) { |
+ NOTREACHED() << "Property " << shill::kPassphraseProperty |
+ << " for service with guid " << guid |
+ << " is not a string"; |
+ return; |
+ } |
+ |
+ guid_to_passphrase_[guid] = passphrase; |
+} |
+ |
+void WifiConfigObserverChromeOs::TryToSyncNetwork( |
+ const chromeos::NetworkState* network) { |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ const std::string device_policy_id = ""; |
+ ::onc::ONCSource onc_source; |
+ if (managed_network_configuration_handler_->FindPolicyByGUID( |
+ device_policy_id, network->guid(), &onc_source) || |
+ managed_network_configuration_handler_->FindPolicyByGUID( |
+ user_hash_, network->guid(), &onc_source)) |
+ return; |
+ |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ if (network->type() != shill::kTypeWifi) // XXX check hdr |
+ return; |
+ |
+ LOG(ERROR) << "*** QUICHE: " << __func__ << ": " |
+ << "network " << network << " " |
+ << "path " << network->path() << " " |
+ << "connection state " << network->connection_state(); |
+ if (!network->IsConnectedState()) |
+ return; // Wait until we complete the connection. |
+ |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ WifiSecurityClass security_class = |
+ WifiSecurityClassFromShillSecurity(network->security_class()); |
+ if (!WifiSecurityClassIsSyncable(security_class)) |
+ return; |
+ |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ std::string passphrase; |
+ if (WifiSecurityClassSupportsPassphrases(security_class)) { |
+ const auto guid_to_passphrase_it = |
+ guid_to_passphrase_.find(network->guid()); |
+ if (guid_to_passphrase_it != guid_to_passphrase_.end()) { |
+ passphrase = guid_to_passphrase_it->second; |
+ } else if (WifiSecurityClassRequiresPassphrase(security_class)) { |
+ LOG(ERROR) << "Required passphrase is missing; skipping sync"; |
+ return; |
+ } |
+ } |
+ guid_to_passphrase_.erase(network->guid()); |
+ |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ scoped_ptr<WifiCredential> credential = |
+ WifiCredential::Create(network->raw_ssid(), security_class, passphrase); |
+ if (!credential) { |
+ LOG(ERROR) << "Failed to create credential; skipping sync"; |
+ return; |
+ } |
+ |
+ LOG(ERROR) << "*** QUICHE: " << __func__; |
+ if (syncable_service_) |
+ syncable_service_->AddToSyncedNetworks(*credential); |
+ else |
+ credentials_awaiting_syncable_service_.push_back(*credential); |
+ |
+ // user_configured_service_guids_.erase(network->guid()); |
+} |
+ |
+} // namespace wifi_sync |