| 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
|
|
|