diff options
author | stevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-09 04:10:05 +0000 |
---|---|---|
committer | stevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-09 04:10:05 +0000 |
commit | b4003ac004bd391e574ca360fa9567cebc3dee08 (patch) | |
tree | b6acf9a2719778785ec145beec4dfbec337cc346 | |
parent | fe8ea750ae210a9db49eacb2289aa96746e98eb9 (diff) | |
download | chromium_src-b4003ac004bd391e574ca360fa9567cebc3dee08.zip chromium_src-b4003ac004bd391e574ca360fa9567cebc3dee08.tar.gz chromium_src-b4003ac004bd391e574ca360fa9567cebc3dee08.tar.bz2 |
Convert all connect code to use NetworkHandler instead of NetworkLibrary
* Eliminates kUseNewNetworkConnectionHandler
* Converts *_config_view to NetworkStateHandler + network_connect
* Migrates non Chrome/Browser dependent network_connect code to
ash::network_connect.
BUG=263978
R=gauravsh@chromium.org, pneubeck@chromium.org
Review URL: https://codereview.chromium.org/21046008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@216568 0039d316-1c4b-4281-b951-d872f2087c98
42 files changed, 1698 insertions, 1175 deletions
diff --git a/ash/system/chromeos/network/network_connect.cc b/ash/system/chromeos/network/network_connect.cc index 5c62499..b68f19a 100644 --- a/ash/system/chromeos/network/network_connect.cc +++ b/ash/system/chromeos/network/network_connect.cc @@ -13,45 +13,71 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "chromeos/login/login_state.h" +#include "chromeos/network/device_state.h" +#include "chromeos/network/network_configuration_handler.h" #include "chromeos/network/network_connection_handler.h" +#include "chromeos/network/network_event_log.h" +#include "chromeos/network/network_profile.h" +#include "chromeos/network/network_profile_handler.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" #include "grit/ash_strings.h" #include "third_party/cros_system_api/dbus/service_constants.h" #include "ui/base/l10n/l10n_util.h" +using chromeos::DeviceState; +using chromeos::NetworkConfigurationHandler; using chromeos::NetworkConnectionHandler; using chromeos::NetworkHandler; +using chromeos::NetworkProfile; +using chromeos::NetworkProfileHandler; using chromeos::NetworkState; namespace ash { namespace { +// Returns true for carriers that can be activated through Shill instead of +// through a WebUI dialog. +bool IsDirectActivatedCarrier(const std::string& carrier) { + if (carrier == shill::kCarrierSprint) + return true; + return false; +} + void OnConnectFailed(const std::string& service_path, + gfx::NativeWindow owning_window, const std::string& error_name, scoped_ptr<base::DictionaryValue> error_data) { - VLOG(1) << "Connect Failed for " << service_path << ": " << error_name; - if (error_name == NetworkConnectionHandler::kErrorPassphraseRequired) { - // TODO(stevenjb): Possibly add inline UI to handle passphrase entry here. - ash::Shell::GetInstance()->system_tray_delegate()->ConfigureNetwork( - service_path); - return; - } - if (error_name == NetworkConnectionHandler::kErrorActivationRequired || - error_name == NetworkConnectionHandler::kErrorCertificateRequired || + NET_LOG_ERROR("Connect Failed: " + error_name, service_path); + + if (error_name == NetworkConnectionHandler::kErrorPassphraseRequired || error_name == NetworkConnectionHandler::kErrorConfigurationRequired || error_name == NetworkConnectionHandler::kErrorAuthenticationRequired) { ash::Shell::GetInstance()->system_tray_delegate()->ConfigureNetwork( service_path); return; } + + if (error_name == NetworkConnectionHandler::kErrorCertificateRequired) { + ash::Shell::GetInstance()->system_tray_delegate()->EnrollOrConfigureNetwork( + service_path, owning_window); + return; + } + + if (error_name == NetworkConnectionHandler::kErrorActivationRequired) { + network_connect::ActivateCellular(service_path); + return; + } + if (error_name == NetworkConnectionHandler::kErrorConnected || error_name == NetworkConnectionHandler::kErrorConnecting) { ash::Shell::GetInstance()->system_tray_delegate()->ShowNetworkSettings( service_path); return; } + // Shill does not always provide a helpful error. In this case, show the // configuration UI and a notification. See crbug.com/217033 for an example. if (error_name == NetworkConnectionHandler::kErrorConnectFailed) { @@ -63,27 +89,197 @@ void OnConnectFailed(const std::string& service_path, } void OnConnectSucceeded(const std::string& service_path) { - VLOG(1) << "Connect Succeeded for " << service_path; + NET_LOG_USER("Connect Succeeded", service_path); + ash::Shell::GetInstance()->system_tray_notifier()->NotifyClearNetworkMessage( + NetworkObserver::ERROR_CONNECT_FAILED); +} + +// If |check_error_state| is true, error state for the network is checked, +// otherwise any current error state is ignored (e.g. for recently configured +// networks or repeat connect attempts). |owning_window| will be used to parent +// any configuration UI on failure and may be NULL (in which case the default +// window will be used). +void CallConnectToNetwork(const std::string& service_path, + bool check_error_state, + gfx::NativeWindow owning_window) { + NET_LOG_USER("ConnectToNetwork", service_path); + ash::Shell::GetInstance()->system_tray_notifier()->NotifyClearNetworkMessage( NetworkObserver::ERROR_CONNECT_FAILED); + + NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork( + service_path, + base::Bind(&OnConnectSucceeded, service_path), + base::Bind(&OnConnectFailed, service_path, owning_window), + check_error_state); +} + +void OnActivateFailed(const std::string& service_path, + const std::string& error_name, + scoped_ptr<base::DictionaryValue> error_data) { + NET_LOG_ERROR("Unable to activate network", service_path); +} + +void OnActivateSucceeded(const std::string& service_path) { + NET_LOG_USER("Activation Succeeded", service_path); +} + +void OnConfigureFailed(const std::string& error_name, + scoped_ptr<base::DictionaryValue> error_data) { + NET_LOG_ERROR("Unable to configure network", ""); +} + +void OnConfigureSucceeded(const std::string& service_path) { + NET_LOG_USER("Configure Succeeded", service_path); + // After configuring a network, ignore any (possibly stale) error state. + const bool check_error_state = false; + const gfx::NativeWindow owning_window = NULL; + CallConnectToNetwork(service_path, check_error_state, owning_window); +} + +void SetPropertiesFailed(const std::string& desc, + const std::string& service_path, + const std::string& config_error_name, + scoped_ptr<base::DictionaryValue> error_data) { + NET_LOG_ERROR(desc + ": Failed: " + config_error_name, service_path); +} + +void SetPropertiesToClear(base::DictionaryValue* properties_to_set, + std::vector<std::string>* properties_to_clear) { + // Move empty string properties to properties_to_clear. + for (base::DictionaryValue::Iterator iter(*properties_to_set); + !iter.IsAtEnd(); iter.Advance()) { + std::string value_str; + if (iter.value().GetAsString(&value_str) && value_str.empty()) + properties_to_clear->push_back(iter.key()); + } + // Remove cleared properties from properties_to_set. + for (std::vector<std::string>::iterator iter = properties_to_clear->begin(); + iter != properties_to_clear->end(); ++iter) { + properties_to_set->RemoveWithoutPathExpansion(*iter, NULL); + } +} + +void ClearPropertiesAndConnect( + const std::string& service_path, + const std::vector<std::string>& properties_to_clear) { + NET_LOG_USER("ClearPropertiesAndConnect", service_path); + // After configuring a network, ignore any (possibly stale) error state. + const bool check_error_state = false; + const gfx::NativeWindow owning_window = NULL; + NetworkHandler::Get()->network_configuration_handler()->ClearProperties( + service_path, + properties_to_clear, + base::Bind(&CallConnectToNetwork, + service_path, check_error_state, + owning_window), + base::Bind(&SetPropertiesFailed, "ClearProperties", service_path)); +} + +std::string GetNetworkProfilePath(bool shared) { + // No need to specify a profile if not logged in and authenticated. + if (!chromeos::LoginState::Get()->IsUserAuthenticated() && !shared) { + NET_LOG_ERROR("User profile specified before login", ""); + shared = true; + } + + if (!shared) { + const NetworkProfile* profile = + NetworkHandler::Get()->network_profile_handler()-> + GetDefaultUserProfile(); + if (profile) + return profile->path; + NET_LOG_ERROR("No user profile for unshared network configuration", ""); + } + + return NetworkProfileHandler::kSharedProfilePath; +} + +void ConfigureSetProfileSucceeded( + const std::string& service_path, + scoped_ptr<base::DictionaryValue> properties_to_set) { + std::vector<std::string> properties_to_clear; + SetPropertiesToClear(properties_to_set.get(), &properties_to_clear); + NetworkHandler::Get()->network_configuration_handler()->SetProperties( + service_path, + *properties_to_set, + base::Bind(&ClearPropertiesAndConnect, + service_path, + properties_to_clear), + base::Bind(&SetPropertiesFailed, "SetProperties", service_path)); } } // namespace namespace network_connect { -void ConnectToNetwork(const std::string& service_path) { - const NetworkState* network = NetworkHandler::Get()->network_state_handler()-> +void ConnectToNetwork(const std::string& service_path, + gfx::NativeWindow owning_window) { + const bool check_error_state = true; + CallConnectToNetwork(service_path, check_error_state, owning_window); +} + +void ActivateCellular(const std::string& service_path) { + NET_LOG_USER("ActivateCellular", service_path); + const DeviceState* cellular_device = + NetworkHandler::Get()->network_state_handler()-> + GetDeviceStateByType(flimflam::kTypeCellular); + if (!cellular_device) { + NET_LOG_ERROR("ActivateCellular with no Device", service_path); + return; + } + if (!IsDirectActivatedCarrier(cellular_device->carrier())) { + // For non direct activation, show the mobile setup dialog which can be + // used to activate the network. + ash::Shell::GetInstance()->system_tray_delegate()->ShowMobileSetup( + service_path); + return; + } + const NetworkState* cellular = + NetworkHandler::Get()->network_state_handler()-> GetNetworkState(service_path); - if (!network) + if (!cellular || cellular->type() != flimflam::kTypeCellular) { + NET_LOG_ERROR("ActivateCellular with no Service", service_path); return; - ash::Shell::GetInstance()->system_tray_notifier()->NotifyClearNetworkMessage( - NetworkObserver::ERROR_CONNECT_FAILED); - NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork( + } + if (cellular->activation_state() == flimflam::kActivationStateActivated) { + NET_LOG_ERROR("ActivateCellular for activated service", service_path); + return; + } + + NetworkHandler::Get()->network_connection_handler()->ActivateNetwork( service_path, - base::Bind(&OnConnectSucceeded, service_path), - base::Bind(&OnConnectFailed, service_path), - true /* check_error_state */); + "", // carrier + base::Bind(&OnActivateSucceeded, service_path), + base::Bind(&OnActivateFailed, service_path)); +} + +void ConfigureNetworkAndConnect(const std::string& service_path, + const base::DictionaryValue& properties, + bool shared) { + NET_LOG_USER("ConfigureNetworkAndConnect", service_path); + + scoped_ptr<base::DictionaryValue> properties_to_set(properties.DeepCopy()); + + std::string profile_path = GetNetworkProfilePath(shared); + NetworkHandler::Get()->network_configuration_handler()->SetNetworkProfile( + service_path, profile_path, + base::Bind(&ConfigureSetProfileSucceeded, + service_path, base::Passed(&properties_to_set)), + base::Bind(&SetPropertiesFailed, + "SetProfile: " + profile_path, service_path)); +} + +void CreateConfigurationAndConnect(base::DictionaryValue* properties, + bool shared) { + NET_LOG_USER("CreateConfigurationAndConnect", ""); + std::string profile_path = GetNetworkProfilePath(shared); + properties->SetStringWithoutPathExpansion( + flimflam::kProfileProperty, profile_path); + NetworkHandler::Get()->network_configuration_handler()->CreateConfiguration( + *properties, + base::Bind(&OnConfigureSucceeded), + base::Bind(&OnConfigureFailed)); } string16 ErrorString(const std::string& error) { diff --git a/ash/system/chromeos/network/network_connect.h b/ash/system/chromeos/network/network_connect.h index 3966140..65c430d 100644 --- a/ash/system/chromeos/network/network_connect.h +++ b/ash/system/chromeos/network/network_connect.h @@ -9,12 +9,35 @@ #include "ash/ash_export.h" #include "base/strings/string16.h" +#include "ui/gfx/native_widget_types.h" // gfx::NativeWindow + +namespace base { +class DictionaryValue; +} namespace ash { namespace network_connect { -// Request a network connection and handle any errors and notifications. -ASH_EXPORT void ConnectToNetwork(const std::string& service_path); +// Requests a network connection and handles any errors and notifications. +// |owning_window| is used to parent any UI on failure (e.g. for certificate +// enrollment). If NULL, the default window will be used. +ASH_EXPORT void ConnectToNetwork(const std::string& service_path, + gfx::NativeWindow owning_window); + +// Requests network activation and handles any errors and notifications. +ASH_EXPORT void ActivateCellular(const std::string& service_path); + +// Configures a network with a dictionary of Shill properties, then sends a +// connect request. The profile is set according to 'shared' if allowed. +ASH_EXPORT void ConfigureNetworkAndConnect( + const std::string& service_path, + const base::DictionaryValue& properties, + bool shared); + +// Requests a new network configuration to be created from a dictionary of +// Shill properties. The profile used is determined by |shared|. +ASH_EXPORT void CreateConfigurationAndConnect(base::DictionaryValue* properties, + bool shared); // Returns the localized string for shill error string |error|. ASH_EXPORT base::string16 ErrorString(const std::string& error); diff --git a/ash/system/chromeos/network/network_state_list_detailed_view.cc b/ash/system/chromeos/network/network_state_list_detailed_view.cc index abc888a..64e6d3b 100644 --- a/ash/system/chromeos/network/network_state_list_detailed_view.cc +++ b/ash/system/chromeos/network/network_state_list_detailed_view.cc @@ -315,12 +315,8 @@ void NetworkStateListDetailedView::OnViewClicked(views::View* sender) { if (!network || network->IsConnectedState() || network->IsConnectingState()) { Shell::GetInstance()->system_tray_delegate()->ShowNetworkSettings( service_path); - } else if (CommandLine::ForCurrentProcess()->HasSwitch( - chromeos::switches::kUseNewNetworkConnectionHandler)) { - ash::network_connect::ConnectToNetwork(service_path); } else { - Shell::GetInstance()->system_tray_delegate()->ConnectToNetwork( - service_path); + ash::network_connect::ConnectToNetwork(service_path, NULL); } } diff --git a/ash/system/tray/system_tray_delegate.h b/ash/system/tray/system_tray_delegate.h index 6c76b57..d6f3c3d 100644 --- a/ash/system/tray/system_tray_delegate.h +++ b/ash/system/tray/system_tray_delegate.h @@ -15,6 +15,7 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" #include "ui/gfx/image/image_skia.h" +#include "ui/gfx/native_widget_types.h" namespace base { class TimeDelta; @@ -251,8 +252,11 @@ class SystemTrayDelegate { // Shows UI to configure or activate the network specified by |network_id|. virtual void ConfigureNetwork(const std::string& network_id) = 0; - // Sends a connect request for the network specified by |network_id|. - virtual void ConnectToNetwork(const std::string& network_id) = 0; + // Shows UI to enroll the network specified by |network_id| if appropriate, + // otherwise behaves the same as ConfigureNetwork. |parent_window| is used + // to parent any configuration UI. If NULL a default window will be used. + virtual void EnrollOrConfigureNetwork(const std::string& network_id, + gfx::NativeWindow parent_window) = 0; // Shows UI to manage bluetooth devices. virtual void ManageBluetoothDevices() = 0; @@ -263,6 +267,9 @@ class SystemTrayDelegate { // Shows UI to unlock a mobile sim. virtual void ShowMobileSimDialog() = 0; + // Shows UI to setup a mobile network. + virtual void ShowMobileSetup(const std::string& network_id) = 0; + // Shows UI to connect to an unlisted wifi network. virtual void ShowOtherWifi() = 0; diff --git a/ash/system/tray/test_system_tray_delegate.cc b/ash/system/tray/test_system_tray_delegate.cc index 33d912ae..d516a76 100644 --- a/ash/system/tray/test_system_tray_delegate.cc +++ b/ash/system/tray/test_system_tray_delegate.cc @@ -212,7 +212,9 @@ void TestSystemTrayDelegate::GetDriveOperationStatusList( void TestSystemTrayDelegate::ConfigureNetwork(const std::string& network_id) { } -void TestSystemTrayDelegate::ConnectToNetwork(const std::string& network_id) { +void TestSystemTrayDelegate::EnrollOrConfigureNetwork( + const std::string& network_id, + gfx::NativeWindow parent_window) { } void TestSystemTrayDelegate::ManageBluetoothDevices() { @@ -229,6 +231,9 @@ bool TestSystemTrayDelegate::IsBluetoothDiscovering() { void TestSystemTrayDelegate::ShowMobileSimDialog() { } +void TestSystemTrayDelegate::ShowMobileSetup(const std::string& network_id) { +} + void TestSystemTrayDelegate::ShowOtherWifi() { } diff --git a/ash/system/tray/test_system_tray_delegate.h b/ash/system/tray/test_system_tray_delegate.h index 26a3dc7..3b4ede7 100644 --- a/ash/system/tray/test_system_tray_delegate.h +++ b/ash/system/tray/test_system_tray_delegate.h @@ -69,11 +69,14 @@ class TestSystemTrayDelegate : public SystemTrayDelegate { virtual void GetDriveOperationStatusList( ash::DriveOperationStatusList*) OVERRIDE; virtual void ConfigureNetwork(const std::string& network_id) OVERRIDE; - virtual void ConnectToNetwork(const std::string& network_id) OVERRIDE; + virtual void EnrollOrConfigureNetwork( + const std::string& network_id, + gfx::NativeWindow parent_window) OVERRIDE; virtual void ManageBluetoothDevices() OVERRIDE; virtual void ToggleBluetooth() OVERRIDE; virtual bool IsBluetoothDiscovering() OVERRIDE; virtual void ShowMobileSimDialog() OVERRIDE; + virtual void ShowMobileSetup(const std::string& network_id) OVERRIDE; virtual void ShowOtherWifi() OVERRIDE; virtual void ShowOtherVPN() OVERRIDE; virtual void ShowOtherCellular() OVERRIDE; diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 1d42cfb..71e06a1 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc @@ -1178,12 +1178,6 @@ const Experiment kExperiments[] = { kOsCrOS, SINGLE_VALUE_TYPE(chromeos::switches::kUseNewNetworkConfigurationHandlers), }, - { "use-new-network-connection-handler", - IDS_FLAGS_CHROMEOS_USE_NEW_NETWORK_CONNECTION_HANDLER_NAME, - IDS_FLAGS_CHROMEOS_USE_NEW_NETWORK_CONNECTION_HANDLER_DESCRIPTION, - kOsCrOS, - SINGLE_VALUE_TYPE(chromeos::switches::kUseNewNetworkConnectionHandler), - }, { "ash-audio-device-menu", IDS_FLAGS_ASH_AUDIO_DEVICE_MENU_NAME, diff --git a/chrome/browser/chromeos/cros/network_library.cc b/chrome/browser/chromeos/cros/network_library.cc index c84eaaa..8c6f558 100644 --- a/chrome/browser/chromeos/cros/network_library.cc +++ b/chrome/browser/chromeos/cros/network_library.cc @@ -15,6 +15,7 @@ #include "chrome/browser/chromeos/cros/native_network_parser.h" #include "chrome/browser/chromeos/cros/network_library_impl_cros.h" #include "chrome/browser/chromeos/cros/network_library_impl_stub.h" +#include "chrome/browser/chromeos/enrollment_dialog_view.h" #include "chrome/common/net/x509_certificate_model.h" #include "chromeos/network/certificate_pattern.h" #include "chromeos/network/certificate_pattern_matcher.h" @@ -331,6 +332,10 @@ bool Network::RequiresUserProfile() const { void Network::CopyCredentialsFromRemembered(Network* remembered) { } +void Network::SetEnrollmentDelegate(EnrollmentDelegate* delegate) { + enrollment_delegate_.reset(delegate); +} + void Network::SetValueProperty(const char* prop, const base::Value& value) { DCHECK(prop); if (!EnsureRunningOnChromeOS()) diff --git a/chrome/browser/chromeos/cros/network_library.h b/chrome/browser/chromeos/cros/network_library.h index ba7a6d3..e4ebbb0 100644 --- a/chrome/browser/chromeos/cros/network_library.h +++ b/chrome/browser/chromeos/cros/network_library.h @@ -27,9 +27,10 @@ namespace chromeos { +class CertificatePattern; +class EnrollmentDelegate; class NetworkDeviceParser; class NetworkParser; -class CertificatePattern; // This is the list of all implementation classes that are allowed // access to the internals of the network library classes. @@ -296,25 +297,6 @@ class NetworkDevice { DISALLOW_COPY_AND_ASSIGN(NetworkDevice); }; -// A virtual class that can be used to handle certificate enrollment URIs when -// encountered. Also used by unit tests to avoid opening browser windows -// when testing. -class EnrollmentDelegate { - public: - EnrollmentDelegate() {} - virtual ~EnrollmentDelegate() {} - - // Implemented to handle a given certificate enrollment URI. Returns false - // if the enrollment URI doesn't use a scheme that we can handle, and in - // that case, this will be called for any remaining enrollment URIs. - // If enrollment succeeds, then the enrollment handler must run - // |post_action| to finish connecting. - virtual void Enroll(const std::vector<std::string>& uri_list, - const base::Closure& post_action) = 0; - private: - DISALLOW_COPY_AND_ASSIGN(EnrollmentDelegate); -}; - // Contains data common to all network service types. class Network { public: @@ -436,9 +418,7 @@ class Network { // Adopts the given enrollment handler to handle any certificate enrollment // URIs encountered during network connection. - void SetEnrollmentDelegate(EnrollmentDelegate* delegate) { - enrollment_delegate_.reset(delegate); - } + void SetEnrollmentDelegate(EnrollmentDelegate* delegate); virtual bool UpdateStatus(const std::string& key, const base::Value& value, diff --git a/chrome/browser/chromeos/cros/network_library_unittest.cc b/chrome/browser/chromeos/cros/network_library_unittest.cc index 06223fc..41ff24c 100644 --- a/chrome/browser/chromeos/cros/network_library_unittest.cc +++ b/chrome/browser/chromeos/cros/network_library_unittest.cc @@ -16,6 +16,7 @@ #include "base/path_service.h" #include "chrome/browser/chromeos/cros/network_library.h" #include "chrome/browser/chromeos/cros/network_library_impl_stub.h" +#include "chrome/browser/chromeos/enrollment_dialog_view.h" #include "chrome/browser/chromeos/login/mock_user_manager.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/google_apis/test_util.h" @@ -43,7 +44,7 @@ class StubEnrollmentDelegate : public EnrollmentDelegate { : did_enroll(false), correct_args(false) {} - virtual void Enroll(const std::vector<std::string>& uri_list, + virtual bool Enroll(const std::vector<std::string>& uri_list, const base::Closure& closure) OVERRIDE { std::vector<std::string> expected_uri_list; expected_uri_list.push_back("http://youtu.be/dQw4w9WgXcQ"); @@ -53,6 +54,7 @@ class StubEnrollmentDelegate : public EnrollmentDelegate { did_enroll = true; closure.Run(); + return true; } bool did_enroll; diff --git a/chrome/browser/chromeos/enrollment_dialog_view.cc b/chrome/browser/chromeos/enrollment_dialog_view.cc index 31e3762..29cff16 100644 --- a/chrome/browser/chromeos/enrollment_dialog_view.cc +++ b/chrome/browser/chromeos/enrollment_dialog_view.cc @@ -10,6 +10,7 @@ #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_navigator.h" +#include "chromeos/network/network_event_log.h" #include "content/public/common/page_transition_types.h" #include "extensions/common/constants.h" #include "grit/generated_resources.h" @@ -192,7 +193,7 @@ class DialogEnrollmentDelegate : public EnrollmentDelegate { virtual ~DialogEnrollmentDelegate(); // EnrollmentDelegate overrides - virtual void Enroll(const std::vector<std::string>& uri_list, + virtual bool Enroll(const std::vector<std::string>& uri_list, const base::Closure& connect) OVERRIDE; private: @@ -212,8 +213,8 @@ DialogEnrollmentDelegate::DialogEnrollmentDelegate( DialogEnrollmentDelegate::~DialogEnrollmentDelegate() {} -void DialogEnrollmentDelegate::Enroll(const std::vector<std::string>& uri_list, - const base::Closure& connect) { +bool DialogEnrollmentDelegate::Enroll(const std::vector<std::string>& uri_list, + const base::Closure& post_action) { // Keep the closure for later activation if we notice that // a certificate has been added. @@ -229,16 +230,14 @@ void DialogEnrollmentDelegate::Enroll(const std::vector<std::string>& uri_list, EnrollmentDialogView::ShowDialog(owning_window_, network_name_, profile_, - uri, connect); - return; + uri, post_action); + return true; } } - // If we didn't find a scheme we could handle, then don't continue connecting. - // TODO(gspencer): provide a path to display this failure to the user. (but - // for the most part they won't know what it means, since it's probably coming - // from a policy-pushed ONC file). - VLOG(1) << "Couldn't find usable scheme in enrollment URI(s)"; + // No appropriate scheme was found. + NET_LOG_EVENT("No usable enrollment URI", network_name_); + return false; } } // namespace diff --git a/chrome/browser/chromeos/enrollment_dialog_view.h b/chrome/browser/chromeos/enrollment_dialog_view.h index a3cd8f0..b855cac 100644 --- a/chrome/browser/chromeos/enrollment_dialog_view.h +++ b/chrome/browser/chromeos/enrollment_dialog_view.h @@ -6,14 +6,31 @@ #define CHROME_BROWSER_CHROMEOS_ENROLLMENT_DIALOG_VIEW_H_ #include <string> +#include <vector> +#include "base/callback_forward.h" #include "ui/gfx/native_widget_types.h" class Profile; namespace chromeos { -class EnrollmentDelegate; +// An interface that can be used to handle certificate enrollment URIs when +// encountered. Also used by unit tests to avoid opening browser windows +// when testing. +class EnrollmentDelegate { + public: + EnrollmentDelegate() {} + virtual ~EnrollmentDelegate() {} + + // Implemented to handle a given certificate enrollment URI. Returns false + // if the enrollment URI doesn't use a scheme that we can handle. + // |post_action| is called when enrollment completes. + virtual bool Enroll(const std::vector<std::string>& uri_list, + const base::Closure& post_action) = 0; + private: + DISALLOW_COPY_AND_ASSIGN(EnrollmentDelegate); +}; EnrollmentDelegate* CreateEnrollmentDelegate(gfx::NativeWindow owning_window, const std::string& network_name, diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index f6b14b5..55cc35c 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc @@ -183,7 +183,6 @@ std::string DeriveCommandLine(const GURL& start_url, chromeos::switches::kLoginProfile, chromeos::switches::kNaturalScrollDefault, chromeos::switches::kUseNewNetworkConfigurationHandlers, - chromeos::switches::kUseNewNetworkConnectionHandler, gfx::switches::kEnableBrowserTextSubpixelPositioning, gfx::switches::kEnableWebkitTextSubpixelPositioning, views::corewm::switches::kNoDropShadows, diff --git a/chrome/browser/chromeos/mobile/mobile_activator.cc b/chrome/browser/chromeos/mobile/mobile_activator.cc index 2c42584..3e1a82e 100644 --- a/chrome/browser/chromeos/mobile/mobile_activator.cc +++ b/chrome/browser/chromeos/mobile/mobile_activator.cc @@ -8,6 +8,7 @@ #include <map> #include <string> +#include "ash/system/chromeos/network/network_connect.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/file_util.h" @@ -515,7 +516,8 @@ void MobileActivator::ContinueConnecting() { LOG(WARNING) << "Connect failed, will try again in a little bit."; if (network) { LOG(INFO) << "Connecting to: " << network->service_path(); - GetNetworkLibrary()->ConnectToCellularNetwork(network); + ash::network_connect::ConnectToNetwork( + network->service_path(), NULL /* no parent window */); } } } diff --git a/chrome/browser/chromeos/network_login_observer.cc b/chrome/browser/chromeos/network_login_observer.cc index b4d4310..65cbd85 100644 --- a/chrome/browser/chromeos/network_login_observer.cc +++ b/chrome/browser/chromeos/network_login_observer.cc @@ -36,7 +36,7 @@ void NetworkLoginObserver::OnNetworkManagerChanged(NetworkLibrary* cros) { wifi->error() == ERROR_BAD_WEPKEY || wifi->connection_started() || (wifi->encrypted() && wifi->added())) { - NetworkConfigView::Show(wifi, NULL); + NetworkConfigView::Show(wifi->service_path(), NULL); return; // Only support one failure per notification. } } @@ -58,7 +58,7 @@ void NetworkLoginObserver::OnNetworkManagerChanged(NetworkLibrary* cros) { wimax->error() == ERROR_BAD_WEPKEY || wimax->connection_started() || (wimax->passphrase_required() && wimax->added())) { - NetworkConfigView::Show(wimax, NULL); + NetworkConfigView::Show(wimax->service_path(), NULL); return; // Only support one failure per notification. } } @@ -74,7 +74,7 @@ void NetworkLoginObserver::OnNetworkManagerChanged(NetworkLibrary* cros) { << ", added: " << vpn->added(); // Display login dialog for any error or newly added network. if (vpn->error() != ERROR_NO_ERROR || vpn->added()) { - NetworkConfigView::Show(vpn, NULL); + NetworkConfigView::Show(vpn->service_path(), NULL); return; // Only support one failure per notification. } } diff --git a/chrome/browser/chromeos/options/network_config_view.cc b/chrome/browser/chromeos/options/network_config_view.cc index 0a74836..257bbdc 100644 --- a/chrome/browser/chromeos/options/network_config_view.cc +++ b/chrome/browser/chromeos/options/network_config_view.cc @@ -12,7 +12,6 @@ #include "chrome/browser/chromeos/cros/network_property_ui_data.h" #include "chrome/browser/chromeos/login/login_display_host_impl.h" #include "chrome/browser/chromeos/login/user.h" -#include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/options/vpn_config_view.h" #include "chrome/browser/chromeos/options/wifi_config_view.h" #include "chrome/browser/chromeos/options/wimax_config_view.h" @@ -21,7 +20,8 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/host_desktop.h" -#include "chromeos/network/managed_network_configuration_handler.h" +#include "chromeos/network/network_state.h" +#include "chromeos/network/network_state_handler.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" @@ -76,39 +76,38 @@ namespace chromeos { // static const int ChildNetworkConfigView::kInputFieldMinWidth = 270; -NetworkConfigView::NetworkConfigView(Network* network) +NetworkConfigView::NetworkConfigView() : child_config_view_(NULL), delegate_(NULL), advanced_button_(NULL) { DCHECK(GetActiveDialog() == NULL); SetActiveDialog(this); - if (network->type() == TYPE_WIFI) { - child_config_view_ = - new WifiConfigView(this, static_cast<WifiNetwork*>(network)); - } else if (network->type() == TYPE_WIMAX) { - child_config_view_ = - new WimaxConfigView(this, static_cast<WimaxNetwork*>(network)); - } else if (network->type() == TYPE_VPN) { - child_config_view_ = - new VPNConfigView(this, static_cast<VirtualNetwork*>(network)); - } else { +} + +void NetworkConfigView::InitWithNetworkState(const NetworkState* network) { + DCHECK(network); + std::string service_path = network->path(); + if (network->type() == flimflam::kTypeWifi) + child_config_view_ = new WifiConfigView(this, service_path, false); + else if (network->type() == flimflam::kTypeWimax) + child_config_view_ = new WimaxConfigView(this, service_path); + else if (network->type() == flimflam::kTypeVPN) + child_config_view_ = new VPNConfigView(this, service_path); + else NOTREACHED(); - } } -NetworkConfigView::NetworkConfigView(ConnectionType type) - : child_config_view_(NULL), - delegate_(NULL), - advanced_button_(NULL) { - DCHECK(GetActiveDialog() == NULL); - SetActiveDialog(this); - if (type == TYPE_WIFI) { - child_config_view_ = new WifiConfigView(this, false /* show_8021x */); +void NetworkConfigView::InitWithType(const std::string& type) { + if (type == flimflam::kTypeWifi) { + child_config_view_ = new WifiConfigView(this, + "" /* service_path */, + false /* show_8021x */); advanced_button_ = new views::LabelButton(this, l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_ADVANCED_BUTTON)); advanced_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON); - } else if (type == TYPE_VPN) { - child_config_view_ = new VPNConfigView(this); + } else if (type == flimflam::kTypeVPN) { + child_config_view_ = new VPNConfigView(this, + "" /* service_path */); } else { NOTREACHED(); } @@ -120,31 +119,28 @@ NetworkConfigView::~NetworkConfigView() { } // static -void NetworkConfigView::Show(Network* network, gfx::NativeWindow parent) { +void NetworkConfigView::Show(const std::string& service_path, + gfx::NativeWindow parent) { if (GetActiveDialog() != NULL) return; - NetworkConfigView* view = new NetworkConfigView(network); - view->ShowDialog(parent); -} - -// static -void NetworkConfigView::ShowForType(ConnectionType type, - gfx::NativeWindow parent) { - if (GetActiveDialog() != NULL) + NetworkConfigView* view = new NetworkConfigView(); + const NetworkState* network = NetworkHandler::Get()->network_state_handler()-> + GetNetworkState(service_path); + if (!network) { + LOG(ERROR) << "NetworkConfigView::Show called with invalid service_path"; return; - NetworkConfigView* view = new NetworkConfigView(type); + } + view->InitWithNetworkState(network); view->ShowDialog(parent); } // static -void NetworkConfigView::ShowForPath(const std::string& path, +void NetworkConfigView::ShowForType(const std::string& type, gfx::NativeWindow parent) { if (GetActiveDialog() != NULL) return; - Network* network = NetworkLibrary::Get()->FindNetworkByPath(path); - if (!network) - return; - NetworkConfigView* view = new NetworkConfigView(network); + NetworkConfigView* view = new NetworkConfigView(); + view->InitWithType(type); view->ShowDialog(parent); } @@ -219,7 +215,9 @@ void NetworkConfigView::ShowAdvancedView() { RemoveChildView(child_config_view_); delete child_config_view_; // For now, there is only an advanced view for Wi-Fi 802.1X. - child_config_view_ = new WifiConfigView(this, true /* show_8021x */); + child_config_view_ = new WifiConfigView(this, + "" /* service_path */, + true /* show_8021x */); AddChildView(child_config_view_); // Resize the window to be able to hold the new widgets. gfx::Size size = views::Widget::GetLocalizedContentsSize( @@ -271,6 +269,20 @@ void NetworkConfigView::ShowDialog(gfx::NativeWindow parent) { window->Show(); } +// ChildNetworkConfigView + +ChildNetworkConfigView::ChildNetworkConfigView( + NetworkConfigView* parent, + const std::string& service_path) + : parent_(parent), + service_path_(service_path) { +} + +ChildNetworkConfigView::~ChildNetworkConfigView() { +} + +// ControlledSettingIndicatorView + ControlledSettingIndicatorView::ControlledSettingIndicatorView() : managed_(false), image_view_(NULL) { @@ -301,17 +313,6 @@ gfx::Size ControlledSettingIndicatorView::GetPreferredSize() { : gfx::Size(); } -// static -const base::DictionaryValue* NetworkConfigView::FindPolicyForActiveUser( - const Network* network, - onc::ONCSource* onc_source) { - const User* user = UserManager::Get()->GetActiveUser(); - std::string username_hash = user ? user->username_hash() : std::string(); - std::string guid = network->unique_id(); - return NetworkHandler::Get()->managed_network_configuration_handler() - ->FindPolicyByGUID(username_hash, guid, onc_source); -} - void ControlledSettingIndicatorView::Layout() { image_view_->SetBounds(0, 0, width(), height()); } diff --git a/chrome/browser/chromeos/options/network_config_view.h b/chrome/browser/chromeos/options/network_config_view.h index 26b3905..f51e3e7 100644 --- a/chrome/browser/chromeos/options/network_config_view.h +++ b/chrome/browser/chromeos/options/network_config_view.h @@ -9,7 +9,6 @@ #include "base/compiler_specific.h" #include "base/strings/string16.h" -#include "chrome/browser/chromeos/cros/network_library.h" #include "ui/gfx/native_widget_types.h" // gfx::NativeWindow #include "ui/views/controls/button/button.h" // views::ButtonListener #include "ui/views/window/dialog_delegate.h" @@ -27,6 +26,7 @@ namespace chromeos { class ChildNetworkConfigView; class NetworkPropertyUIData; +class NetworkState; // A dialog box for showing a password textfield. class NetworkConfigView : public views::DialogDelegateView, @@ -45,9 +45,10 @@ class NetworkConfigView : public views::DialogDelegateView, }; // Shows a network connection dialog if none is currently visible. - static void Show(Network* network, gfx::NativeWindow parent); - static void ShowForType(ConnectionType type, gfx::NativeWindow parent); - static void ShowForPath(const std::string& path, gfx::NativeWindow parent); + static void Show(const std::string& service_path, gfx::NativeWindow parent); + // Shows a dialog to configure a new network. |type| must be a valid Shill + // 'Type' property value. + static void ShowForType(const std::string& type, gfx::NativeWindow parent); // Returns corresponding native window. gfx::NativeWindow GetNativeWindow() const; @@ -75,10 +76,6 @@ class NetworkConfigView : public views::DialogDelegateView, delegate_ = delegate; } - static const base::DictionaryValue* FindPolicyForActiveUser( - const Network* network, - onc::ONCSource* onc_source); - protected: // views::View overrides: virtual void Layout() OVERRIDE; @@ -87,11 +84,13 @@ class NetworkConfigView : public views::DialogDelegateView, const ViewHierarchyChangedDetails& details) OVERRIDE; private: + NetworkConfigView(); + virtual ~NetworkConfigView(); + // Login dialog for known networks. - explicit NetworkConfigView(Network* network); + void InitWithNetworkState(const NetworkState* network); // Login dialog for new/hidden networks. - explicit NetworkConfigView(ConnectionType type); - virtual ~NetworkConfigView(); + void InitWithType(const std::string& type); // Creates and shows a dialog containing this view. void ShowDialog(gfx::NativeWindow parent); @@ -115,12 +114,11 @@ class NetworkConfigView : public views::DialogDelegateView, // methods, which are called by NetworkConfigView. class ChildNetworkConfigView : public views::View { public: - ChildNetworkConfigView(NetworkConfigView* parent, Network* network) - : service_path_(network->service_path()), - parent_(parent) {} - explicit ChildNetworkConfigView(NetworkConfigView* parent) - : parent_(parent) {} - virtual ~ChildNetworkConfigView() {} + // If |service_path| is NULL, a dialog for configuring a new network will + // be created. + ChildNetworkConfigView(NetworkConfigView* parent, + const std::string& service_path); + virtual ~ChildNetworkConfigView(); // Get the title to show for the dialog. virtual string16 GetTitle() const = 0; @@ -146,8 +144,8 @@ class ChildNetworkConfigView : public views::View { static const int kInputFieldMinWidth; protected: - std::string service_path_; NetworkConfigView* parent_; + std::string service_path_; private: DISALLOW_COPY_AND_ASSIGN(ChildNetworkConfigView); diff --git a/chrome/browser/chromeos/options/network_connect.cc b/chrome/browser/chromeos/options/network_connect.cc index c44822b..54dd043 100644 --- a/chrome/browser/chromeos/options/network_connect.cc +++ b/chrome/browser/chromeos/options/network_connect.cc @@ -12,8 +12,8 @@ #include "base/command_line.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/chromeos/cros/network_library.h" #include "chrome/browser/chromeos/enrollment_dialog_view.h" +#include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/options/network_config_view.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/browser_finder.h" @@ -21,6 +21,13 @@ #include "chrome/browser/ui/webui/chromeos/mobile_setup_dialog.h" #include "chrome/common/url_constants.h" #include "chromeos/chromeos_switches.h" +#include "chromeos/network/certificate_pattern.h" +#include "chromeos/network/certificate_pattern_matcher.h" +#include "chromeos/network/managed_network_configuration_handler.h" +#include "chromeos/network/network_event_log.h" +#include "chromeos/network/network_handler.h" +#include "chromeos/network/network_state.h" +#include "chromeos/network/network_state_handler.h" #include "content/public/browser/user_metrics.h" #include "grit/generated_resources.h" #include "net/base/escape.h" @@ -28,84 +35,28 @@ #include "ui/base/l10n/l10n_util.h" namespace chromeos { -namespace network_connect { namespace { -void DoConnect(Network* network, gfx::NativeWindow parent_window) { - NetworkLibrary* cros = NetworkLibrary::Get(); - if (network->type() == TYPE_VPN) { - VirtualNetwork* vpn = static_cast<VirtualNetwork*>(network); - if (vpn->NeedMoreInfoToConnect()) { - // Show the connection UI if info for a field is missing. - NetworkConfigView::Show(vpn, parent_window); - } else { - cros->ConnectToVirtualNetwork(vpn); - // Connection failures are responsible for updating the UI, including - // reopening dialogs. - } - } else if (network->type() == TYPE_WIFI) { - WifiNetwork* wifi = static_cast<WifiNetwork*>(network); - if (wifi->IsPassphraseRequired()) { - // Show the connection UI if we require a passphrase. - NetworkConfigView::Show(wifi, parent_window); - } else { - cros->ConnectToWifiNetwork(wifi); - // Connection failures are responsible for updating the UI, including - // reopening dialogs. - } - } else if (network->type() == TYPE_WIMAX) { - WimaxNetwork* wimax = static_cast<WimaxNetwork*>(network); - if (wimax->passphrase_required()) { - // Show the connection UI if we require a passphrase. - NetworkConfigView::Show(wimax, parent_window); - } else { - cros->ConnectToWimaxNetwork(wimax); - // Connection failures are responsible for updating the UI, including - // reopening dialogs. - } - } else if (network->type() == TYPE_CELLULAR) { - CellularNetwork* cellular = static_cast<CellularNetwork*>(network); - if (cellular->activation_state() != ACTIVATION_STATE_ACTIVATED || - cellular->out_of_credits()) { - ActivateCellular(cellular->service_path()); - } else { - cros->ConnectToCellularNetwork(cellular); - } - } +void EnrollmentComplete(const std::string& service_path) { + NET_LOG_USER("Enrollment Complete", service_path); } -} // namespace - -void ActivateCellular(const std::string& service_path) { - chromeos::NetworkLibrary* cros = - chromeos::NetworkLibrary::Get(); - if (!cros->CellularDeviceUsesDirectActivation()) { - // For non direct activation, show the mobile setup dialog which can be - // used to activate the network. - ShowMobileSetup(service_path); - return; - } - chromeos::CellularNetwork* cellular = - cros->FindCellularNetworkByPath(service_path); - if (!cellular) - return; - if (cellular->activation_state() != chromeos::ACTIVATION_STATE_ACTIVATED) - cellular->StartActivation(); - return; } +namespace network_connect { + void ShowMobileSetup(const std::string& service_path) { - NetworkLibrary* cros = NetworkLibrary::Get(); - const CellularNetwork* cellular = - cros->FindCellularNetworkByPath(service_path); - if (cellular && !cellular->activated() && - cellular->activate_over_non_cellular_network() && - (!cros->connected_network() || !cros->connected_network()->online())) { - NetworkTechnology technology = cellular->network_technology(); + NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); + const NetworkState* cellular = handler->GetNetworkState(service_path); + if (cellular && cellular->type() == flimflam::kTypeCellular && + cellular->activation_state() != flimflam::kActivationStateActivated && + cellular->activate_over_non_cellular_networks() && + !handler->DefaultNetwork()) { + std::string technology = cellular->network_technology(); ash::NetworkObserver::NetworkType network_type = - (technology == chromeos::NETWORK_TECHNOLOGY_LTE || - technology == chromeos::NETWORK_TECHNOLOGY_LTE_ADVANCED) + (technology == flimflam::kNetworkTechnologyLte || + technology == flimflam::kNetworkTechnologyLteAdvanced) ? ash::NetworkObserver::NETWORK_CELLULAR_LTE : ash::NetworkObserver::NETWORK_CELLULAR; ash::Shell::GetInstance()->system_tray_notifier()->NotifySetNetworkMessage( @@ -121,106 +72,94 @@ void ShowMobileSetup(const std::string& service_path) { MobileSetupDialog::Show(service_path); } -ConnectResult ConnectToNetwork(const std::string& service_path, - gfx::NativeWindow parent_window) { - if (CommandLine::ForCurrentProcess()->HasSwitch( - chromeos::switches::kUseNewNetworkConnectionHandler)) { - ash::network_connect::ConnectToNetwork(service_path); - return CONNECT_STARTED; - } - - NetworkLibrary* cros = NetworkLibrary::Get(); - Network* network = cros->FindNetworkByPath(service_path); - if (!network) - return NETWORK_NOT_FOUND; - - if (network->connecting_or_connected()) - return CONNECT_NOT_STARTED; - - if (network->type() == TYPE_ETHERNET) - return CONNECT_NOT_STARTED; // Normally this shouldn't happen - - if (network->type() == TYPE_WIFI || network->type() == TYPE_VPN) { - network->SetEnrollmentDelegate(chromeos::CreateEnrollmentDelegate( - parent_window, network->name(), ProfileManager::GetLastUsedProfile())); - network->AttemptConnection(base::Bind(&DoConnect, network, parent_window)); - return CONNECT_STARTED; - } - - if (network->type() == TYPE_WIMAX) { - WimaxNetwork* wimax = static_cast<WimaxNetwork*>(network); - wimax->AttemptConnection(base::Bind(&DoConnect, wimax, parent_window)); - return CONNECT_STARTED; - } - - if (network->type() == TYPE_CELLULAR) { - CellularNetwork* cellular = static_cast<CellularNetwork*>(network); - if (cellular->NeedsActivation() || cellular->out_of_credits()) { - ActivateCellular(service_path); - return CONNECT_STARTED; - } - if (cellular->activation_state() == ACTIVATION_STATE_ACTIVATING) - return CONNECT_NOT_STARTED; - cros->ConnectToCellularNetwork(cellular); - return CONNECT_STARTED; +void ShowNetworkSettings(const std::string& service_path) { + std::string page = chrome::kInternetOptionsSubPage; + const NetworkState* network = service_path.empty() ? NULL : + NetworkHandler::Get()->network_state_handler()->GetNetworkState( + service_path); + if (network) { + std::string name(network->name()); + if (name.empty() && network->type() == flimflam::kTypeEthernet) + name = l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET); + page += base::StringPrintf( + "?servicePath=%s&networkType=%s&networkName=%s", + net::EscapeUrlEncodedData(service_path, true).c_str(), + net::EscapeUrlEncodedData(network->type(), true).c_str(), + net::EscapeUrlEncodedData(name, false).c_str()); } - - NOTREACHED(); - return CONNECT_NOT_STARTED; + content::RecordAction( + content::UserMetricsAction("OpenInternetOptionsDialog")); + Browser* browser = chrome::FindOrCreateTabbedBrowser( + ProfileManager::GetDefaultProfileOrOffTheRecord(), + chrome::HOST_DESKTOP_TYPE_ASH); + chrome::ShowSettingsSubPage(browser, page); } void HandleUnconfiguredNetwork(const std::string& service_path, gfx::NativeWindow parent_window) { - NetworkLibrary* cros = NetworkLibrary::Get(); - Network* network = cros->FindNetworkByPath(service_path); + const NetworkState* network = NetworkHandler::Get()->network_state_handler()-> + GetNetworkState(service_path); if (!network) { - LOG(WARNING) << "Unknown network: " << service_path; - return; - } - - if (network->type() == TYPE_WIFI || network->type() == TYPE_VPN) { - network->SetEnrollmentDelegate(chromeos::CreateEnrollmentDelegate( - parent_window, network->name(), ProfileManager::GetLastUsedProfile())); - // This will connect to the network only if the network just needs to have - // its certificate configured. Otherwise it will show an enrollment dialog - // if available, or call NetworkConfigView::Show(). - network->AttemptConnection( - base::Bind(&NetworkConfigView::Show, network, parent_window)); + NET_LOG_ERROR("Configuring unknown network", service_path); return; } - if (network->type() == TYPE_WIMAX) { - NetworkConfigView::Show(network, parent_window); + if (network->type() == flimflam::kTypeWifi || + network->type() == flimflam::kTypeWimax || + network->type() == flimflam::kTypeVPN) { + NetworkConfigView::Show(service_path, parent_window); return; } - if (network->type() == TYPE_CELLULAR) { - CellularNetwork* cellular = static_cast<CellularNetwork*>(network); - if (cellular->NeedsActivation()) { - ActivateCellular(service_path); + if (network->type() == flimflam::kTypeCellular) { + if (network->activation_state() != flimflam::kActivationStateActivated) { + ash::network_connect::ActivateCellular(service_path); return; - } else if (cellular->out_of_credits()) { + } + if (network->cellular_out_of_credits()) { ShowMobileSetup(service_path); return; } + // No special configure or setup for |network|, show the settings UI. + ShowNetworkSettings(service_path); + } + NOTREACHED(); +} + +bool EnrollNetwork(const std::string& service_path, + gfx::NativeWindow parent_window) { + const NetworkState* network = NetworkHandler::Get()->network_state_handler()-> + GetNetworkState(service_path); + if (!network) { + NET_LOG_ERROR("Enrolling Unknown network", service_path); + return false; } + // We skip certificate patterns for device policy ONC so that an unmanaged + // user can't get to the place where a cert is presented for them + // involuntarily. + if (network->ui_data().onc_source() == onc::ONC_SOURCE_DEVICE_POLICY) + return false; + + const CertificatePattern& certificate_pattern = + network->ui_data().certificate_pattern(); + if (certificate_pattern.Empty()) + return false; + + NET_LOG_USER("Enrolling", service_path); + + EnrollmentDelegate* enrollment = CreateEnrollmentDelegate( + parent_window, network->name(), ProfileManager::GetDefaultProfile()); + return enrollment->Enroll(certificate_pattern.enrollment_uri_list(), + base::Bind(&EnrollmentComplete, service_path)); +} - // No special configure or setup for |service_path|, show the settings UI. - std::string page = chrome::kInternetOptionsSubPage; - std::string name = network->name(); - if (name.empty() && network->type() == TYPE_ETHERNET) - name = l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET); - page += base::StringPrintf( - "?servicePath=%s&networkType=%d&networkName=%s", - net::EscapeUrlEncodedData(service_path, true).c_str(), - network->type(), - net::EscapeUrlEncodedData(name, false).c_str()); - content::RecordAction( - content::UserMetricsAction("OpenInternetOptionsDialog")); - Browser* browser = chrome::FindOrCreateTabbedBrowser( - ProfileManager::GetDefaultProfileOrOffTheRecord(), - chrome::HOST_DESKTOP_TYPE_ASH); - chrome::ShowSettingsSubPage(browser, page); +const base::DictionaryValue* FindPolicyForActiveUser( + const NetworkState* network, + onc::ONCSource* onc_source) { + const User* user = UserManager::Get()->GetActiveUser(); + std::string username_hash = user ? user->username_hash() : std::string(); + return NetworkHandler::Get()->managed_network_configuration_handler()-> + FindPolicyByGUID(username_hash, network->guid(), onc_source); } } // namespace network_connect diff --git a/chrome/browser/chromeos/options/network_connect.h b/chrome/browser/chromeos/options/network_connect.h index 9872cbc..2d8acbe 100644 --- a/chrome/browser/chromeos/options/network_connect.h +++ b/chrome/browser/chromeos/options/network_connect.h @@ -6,46 +6,47 @@ #define CHROME_BROWSER_CHROMEOS_OPTIONS_NETWORK_CONNECT_H_ #include <string> +#include <vector> +#include "chromeos/network/onc/onc_constants.h" #include "ui/gfx/native_widget_types.h" // gfx::NativeWindow +namespace base { +class DictionaryValue; +} + namespace chromeos { -namespace network_connect { -enum ConnectResult { - NETWORK_NOT_FOUND, - CONNECT_NOT_STARTED, - CONNECT_STARTED -}; +class NetworkState; -// Activate the cellular network associated with |service_path| if direct -// activation is supported, otherwise call ShowMobileSetup. -void ActivateCellular(const std::string& service_path); +namespace network_connect { // Shows the mobile setup dialog which handles: // * Activation for non direct-activation networks // * Showing network plan info void ShowMobileSetup(const std::string& service_path); -// Attempts to connect to the network specified by |service_path|. -// Returns one of the following results: -// NETWORK_NOT_FOUND if the network does not exist. -// CONNECT_NOT_STARTED if no connection attempt was started, e.g. because the -// network is already connected, connecting, or activating. -// CONNECT_STARTED if a connection attempt was started. -ConnectResult ConnectToNetwork(const std::string& service_path, - gfx::NativeWindow parent_window); +// Shows the network settings subpage for |service_path| (or the main +// network settings page if empty). +void ShowNetworkSettings(const std::string& service_path); -// Handle an unconfigured network which might do any of the following: -// * Configure and connect to the network with a matching cert but without -// pcks11id and tpm pin / slot configured. -// * Show the enrollment dialog for the network. -// * Show the configuration dialog for the network. -// * Show the activation dialog for the network. -// * Show the settings UI for the network. +// Handle an unconfigured network: +// * Show the Configure dialog for wifi/wimax/VPN +// * Show the Activation, MobileSetup dialog, or settings page for cellular void HandleUnconfiguredNetwork(const std::string& service_path, gfx::NativeWindow parent_window); +// If the network UIData has a matching enrollment URL, triggers the enrollment +// dialog and returns true. +bool EnrollNetwork(const std::string& service_path, + gfx::NativeWindow parent_window); + +// Looks up the policy for |network| for the current active user and sets +// |onc_source| accordingly. +const base::DictionaryValue* FindPolicyForActiveUser( + const NetworkState* network, + onc::ONCSource* onc_source); + } // namespace network_connect } // namespace chromeos diff --git a/chrome/browser/chromeos/options/passphrase_textfield.cc b/chrome/browser/chromeos/options/passphrase_textfield.cc index 598d192..9cc9bd3 100644 --- a/chrome/browser/chromeos/options/passphrase_textfield.cc +++ b/chrome/browser/chromeos/options/passphrase_textfield.cc @@ -8,12 +8,18 @@ namespace chromeos { -PassphraseTextfield::PassphraseTextfield(bool show_fake) +PassphraseTextfield::PassphraseTextfield() : Textfield(views::Textfield::STYLE_OBSCURED), - show_fake_(show_fake), + show_fake_(false), changed_(true) { +} + +void PassphraseTextfield::SetShowFake(bool show_fake) { + show_fake_ = show_fake; if (show_fake_) SetFakePassphrase(); + else + ClearFakePassphrase(); } void PassphraseTextfield::OnFocus() { diff --git a/chrome/browser/chromeos/options/passphrase_textfield.h b/chrome/browser/chromeos/options/passphrase_textfield.h index 16d5301..1f1b5906 100644 --- a/chrome/browser/chromeos/options/passphrase_textfield.h +++ b/chrome/browser/chromeos/options/passphrase_textfield.h @@ -13,8 +13,10 @@ namespace chromeos { class PassphraseTextfield : public views::Textfield { public: - // If show_already_set is true, then the text field will show a fake password. - explicit PassphraseTextfield(bool show_fake); + PassphraseTextfield(); + + // If show_fake is true, then the text field will show a fake password. + void SetShowFake(bool show_fake); // Override views::Textfield so that when focus is gained, then clear out the // fake password if appropriate. Replace it when focus is lost if the user has diff --git a/chrome/browser/chromeos/options/vpn_config_view.cc b/chrome/browser/chromeos/options/vpn_config_view.cc index d8e019b..4aa6682 100644 --- a/chrome/browser/chromeos/options/vpn_config_view.cc +++ b/chrome/browser/chromeos/options/vpn_config_view.cc @@ -4,19 +4,25 @@ #include "chrome/browser/chromeos/options/vpn_config_view.h" +#include "ash/system/chromeos/network/network_connect.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/chromeos/cros/network_library.h" #include "chrome/browser/chromeos/enrollment_dialog_view.h" +#include "chrome/browser/chromeos/options/network_connect.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/net/x509_certificate_model.h" +#include "chromeos/network/network_configuration_handler.h" +#include "chromeos/network/network_event_log.h" +#include "chromeos/network/network_state.h" +#include "chromeos/network/network_state_handler.h" #include "chromeos/network/network_ui_data.h" #include "chromeos/network/onc/onc_constants.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "grit/theme_resources.h" +#include "third_party/cros_system_api/dbus/service_constants.h" #include "ui/base/events/event.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/combobox_model.h" @@ -35,41 +41,73 @@ namespace { // Root CA certificates that are built into Chrome use this token name. const char* const kRootCertificateTokenName = "Builtin Object Token"; -string16 ProviderTypeToString(chromeos::ProviderType type) { - switch (type) { - case chromeos::PROVIDER_TYPE_L2TP_IPSEC_PSK: +enum ProviderTypeIndex { + PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK = 0, + PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT = 1, + PROVIDER_TYPE_INDEX_OPEN_VPN = 2, + PROVIDER_TYPE_INDEX_MAX = 3, +}; + +string16 ProviderTypeIndexToString(int index) { + switch (index) { + case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK: return l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK); - case chromeos::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: + case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT: return l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT); - case chromeos::PROVIDER_TYPE_OPEN_VPN: + case PROVIDER_TYPE_INDEX_OPEN_VPN: return l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN); - case chromeos::PROVIDER_TYPE_MAX: - break; } NOTREACHED(); return string16(); } +int ProviderTypeToIndex(const std::string& provider_type, + const std::string& client_cert_id) { + if (provider_type == flimflam::kProviderL2tpIpsec) { + if (!client_cert_id.empty()) + return PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT; + else + return PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK; + } else { + DCHECK(provider_type == flimflam::kProviderOpenVpn); + return PROVIDER_TYPE_INDEX_OPEN_VPN; + } +} + // Translates the provider type to the name of the respective ONC dictionary // containing configuration data for the type. -std::string ProviderTypeToONCDictKey(chromeos::ProviderType type) { - switch (type) { - case chromeos::PROVIDER_TYPE_L2TP_IPSEC_PSK: - case chromeos::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: +std::string ProviderTypeIndexToONCDictKey(int provider_type_index) { + switch (provider_type_index) { + case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK: + case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT: return chromeos::onc::vpn::kIPsec; - case chromeos::PROVIDER_TYPE_OPEN_VPN: + case PROVIDER_TYPE_INDEX_OPEN_VPN: return chromeos::onc::vpn::kOpenVPN; - case chromeos::PROVIDER_TYPE_MAX: - break; } - - NOTREACHED() << "Unhandled provider type " << type; + NOTREACHED() << "Unhandled provider type index " << provider_type_index; return std::string(); } +std::string GetPemFromDictionary( + const base::DictionaryValue* provider_properties, + const std::string& key) { + const base::ListValue* pems = NULL; + if (!provider_properties->GetListWithoutPathExpansion(key, &pems)) + return std::string(); + std::string pem; + pems->GetString(0, &pem); + return pem; +} + +void ShillError(const std::string& function, + const std::string& error_name, + scoped_ptr<base::DictionaryValue> error_data) { + NET_LOG_ERROR("Shill Error from VpnConfigView: " + error_name, function); +} + } // namespace namespace chromeos { @@ -124,12 +162,11 @@ ProviderTypeComboboxModel::~ProviderTypeComboboxModel() { } int ProviderTypeComboboxModel::GetItemCount() const { - return PROVIDER_TYPE_MAX; + return PROVIDER_TYPE_INDEX_MAX; } string16 ProviderTypeComboboxModel::GetItemAt(int index) { - ProviderType type = static_cast<ProviderType>(index); - return ProviderTypeToString(type); + return ProviderTypeIndexToString(index); } // VpnServerCACertComboboxModel ------------------------------------------------ @@ -193,16 +230,39 @@ string16 VpnUserCertComboboxModel::GetItemAt(int index) { } // namespace internal -VPNConfigView::VPNConfigView(NetworkConfigView* parent, VirtualNetwork* vpn) - : ChildNetworkConfigView(parent, vpn), - title_(0) { - Init(vpn); -} - -VPNConfigView::VPNConfigView(NetworkConfigView* parent) - : ChildNetworkConfigView(parent), - title_(0) { - Init(NULL); +VPNConfigView::VPNConfigView(NetworkConfigView* parent, + const std::string& service_path) + : ChildNetworkConfigView(parent, service_path), + service_text_modified_(false), + enable_psk_passphrase_(false), + enable_user_cert_(false), + enable_server_ca_cert_(false), + enable_otp_(false), + enable_group_name_(false), + title_(0), + layout_(NULL), + server_textfield_(NULL), + service_text_(NULL), + service_textfield_(NULL), + provider_type_combobox_(NULL), + provider_type_text_label_(NULL), + psk_passphrase_label_(NULL), + psk_passphrase_textfield_(NULL), + user_cert_label_(NULL), + user_cert_combobox_(NULL), + server_ca_cert_label_(NULL), + server_ca_cert_combobox_(NULL), + username_textfield_(NULL), + user_passphrase_textfield_(NULL), + otp_label_(NULL), + otp_textfield_(NULL), + group_name_label_(NULL), + group_name_textfield_(NULL), + save_credentials_checkbox_(NULL), + error_label_(NULL), + provider_type_index_(PROVIDER_TYPE_INDEX_MAX), + weak_ptr_factory_(this) { + Init(); } VPNConfigView::~VPNConfigView() { @@ -243,7 +303,9 @@ bool VPNConfigView::CanLogin() { return false; // Block login if certs are required but user has none. - if (UserCertRequired() && (!HaveUserCerts() || !IsUserCertValid())) + bool cert_required = + GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT; + if (cert_required && (!HaveUserCerts() || !IsUserCertValid())) return false; return true; @@ -283,15 +345,7 @@ void VPNConfigView::ButtonPressed(views::Button* sender, } void VPNConfigView::OnSelectedIndexChanged(views::Combobox* combobox) { - if (combobox == provider_type_combobox_) { - provider_type_ = static_cast<ProviderType>(combobox->selected_index()); - UpdateControls(); - } else if (combobox == user_cert_combobox_ || - combobox == server_ca_cert_combobox_) { - // Do nothing. - } else { - NOTREACHED(); - } + UpdateControls(); UpdateErrorLabel(); UpdateCanLogin(); } @@ -301,77 +355,35 @@ void VPNConfigView::OnCertificatesLoaded(bool initial_load) { } bool VPNConfigView::Login() { - NetworkLibrary* cros = NetworkLibrary::Get(); if (service_path_.empty()) { - NetworkLibrary::VPNConfigData config_data; - switch (provider_type_) { - case PROVIDER_TYPE_L2TP_IPSEC_PSK: - config_data.psk = GetPSKPassphrase(); - config_data.username = GetUsername(); - config_data.user_passphrase = GetUserPassphrase(); - config_data.group_name = GetGroupName(); - break; - case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: { - config_data.server_ca_cert_pem = GetServerCACertPEM(); - config_data.client_cert_pkcs11_id = GetUserCertID(); - config_data.username = GetUsername(); - config_data.user_passphrase = GetUserPassphrase(); - config_data.group_name = GetGroupName(); - break; - } - case PROVIDER_TYPE_OPEN_VPN: - config_data.server_ca_cert_pem = GetServerCACertPEM(); - config_data.client_cert_pkcs11_id = GetUserCertID(); - config_data.username = GetUsername(); - config_data.user_passphrase = GetUserPassphrase(); - config_data.otp = GetOTP(); - break; - case PROVIDER_TYPE_MAX: - break; - } - config_data.save_credentials = GetSaveCredentials(); - cros->ConnectToUnconfiguredVirtualNetwork( - GetService(), GetServer(), provider_type_, config_data); + base::DictionaryValue properties; + // Identifying properties + properties.SetStringWithoutPathExpansion( + flimflam::kTypeProperty, flimflam::kTypeVPN); + properties.SetStringWithoutPathExpansion( + flimflam::kNameProperty, GetService()); + properties.SetStringWithoutPathExpansion( + flimflam::kProviderHostProperty, GetServer()); + properties.SetStringWithoutPathExpansion( + flimflam::kProviderTypeProperty, GetProviderTypeString()); + + SetConfigProperties(&properties); + ash::network_connect::CreateConfigurationAndConnect( + &properties, false /* not shared */); } else { - VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_); + const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()-> + GetNetworkState(service_path_); if (!vpn) { + // Shill no longer knows about this network (edge case). // TODO(stevenjb): Add notification for this. - LOG(WARNING) << "VPN no longer exists: " << service_path_; - return true; // Close dialog. - } - switch (provider_type_) { - case PROVIDER_TYPE_L2TP_IPSEC_PSK: - vpn->SetL2TPIPsecPSKCredentials(GetPSKPassphrase(), - GetUsername(), - GetUserPassphrase(), - GetGroupName()); - break; - case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: { - vpn->SetL2TPIPsecCertCredentials(GetUserCertID(), - GetUsername(), - GetUserPassphrase(), - GetGroupName()); - break; - } - case PROVIDER_TYPE_OPEN_VPN: { - vpn->SetOpenVPNCredentials(GetUserCertID(), - GetUsername(), - GetUserPassphrase(), - GetOTP()); - break; - } - case PROVIDER_TYPE_MAX: - break; + NET_LOG_ERROR("Network not found", service_path_); + return true; // Close dialog } - vpn->SetEnrollmentDelegate( - CreateEnrollmentDelegate(GetWidget()->GetNativeWindow(), - vpn->name(), - ProfileManager::GetLastUsedProfile())); - vpn->SetSaveCredentials(GetSaveCredentials()); - cros->ConnectToVirtualNetwork(vpn); + base::DictionaryValue properties; + SetConfigProperties(&properties); + ash::network_connect::ConfigureNetworkAndConnect( + service_path_, properties, false /* not shared */); } - // Connection failures are responsible for updating the UI, including - // reopening dialogs. return true; // Close dialog. } @@ -393,7 +405,7 @@ const std::string VPNConfigView::GetService() const { const std::string VPNConfigView::GetServer() const { if (server_textfield_ != NULL) return GetTextFromField(server_textfield_, true); - return server_hostname_; + return std::string(); } const std::string VPNConfigView::GetPSKPassphrase() const { @@ -448,44 +460,39 @@ bool VPNConfigView::GetSaveCredentials() const { return save_credentials_checkbox_->checked(); } -void VPNConfigView::Init(VirtualNetwork* vpn) { - if (vpn) { - ProviderType type = vpn->provider_type(); - std::string type_dict_name = ProviderTypeToONCDictKey(type); - - if (type == PROVIDER_TYPE_L2TP_IPSEC_PSK) { - ParseVPNUIProperty(&ca_cert_ui_data_, vpn, type_dict_name, - onc::ipsec::kServerCARef); - ParseVPNUIProperty(&psk_passphrase_ui_data_, vpn, type_dict_name, - onc::ipsec::kPSK); - ParseVPNUIProperty(&group_name_ui_data_, vpn, type_dict_name, - onc::ipsec::kGroup); - } else { // OpenVPN - ParseVPNUIProperty(&ca_cert_ui_data_, vpn, type_dict_name, - onc::openvpn::kServerCARef); - } - ParseVPNUIProperty(&user_cert_ui_data_, vpn, type_dict_name, - onc::vpn::kClientCertRef); - - const std::string credentials_dict_name( - type == PROVIDER_TYPE_L2TP_IPSEC_PSK ? - onc::vpn::kL2TP : type_dict_name); - ParseVPNUIProperty(&username_ui_data_, vpn, credentials_dict_name, - onc::vpn::kUsername); - ParseVPNUIProperty(&user_passphrase_ui_data_, vpn, credentials_dict_name, - onc::vpn::kPassword); - ParseVPNUIProperty(&save_credentials_ui_data_, vpn, credentials_dict_name, - onc::vpn::kSaveCredentials); +int VPNConfigView::GetProviderTypeIndex() const { + if (provider_type_combobox_) + return provider_type_combobox_->selected_index(); + return provider_type_index_; +} + +std::string VPNConfigView::GetProviderTypeString() const { + int index = GetProviderTypeIndex(); + switch (index) { + case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK: + case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT: + return flimflam::kProviderL2tpIpsec; + case PROVIDER_TYPE_INDEX_OPEN_VPN: + return flimflam::kProviderOpenVpn; } + NOTREACHED(); + return std::string(); +} - views::GridLayout* layout = views::GridLayout::CreatePanel(this); - SetLayoutManager(layout); +void VPNConfigView::Init() { + const NetworkState* vpn = NULL; + if (!service_path_.empty()) { + vpn = NetworkHandler::Get()->network_state_handler()-> + GetNetworkState(service_path_); + DCHECK(vpn && vpn->type() == flimflam::kTypeVPN); + } + layout_ = views::GridLayout::CreatePanel(this); + SetLayoutManager(layout_); // Observer any changes to the certificate list. CertLibrary::Get()->AddObserver(this); - const int column_view_set_id = 0; - views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id); + views::ColumnSet* column_set = layout_->AddColumnSet(0); // Label. column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1, views::GridLayout::USE_PREF, 0, 0); @@ -501,232 +508,376 @@ void VPNConfigView::Init(VirtualNetwork* vpn) { // Initialize members. service_text_modified_ = false; - if (vpn) { - provider_type_ = vpn->provider_type(); - // Sets enable_* based on the provider type which we use to control - // which controls to make visible. - UpdateControlsToEnable(); - } else { - // Set the default provider type. - provider_type_ = PROVIDER_TYPE_L2TP_IPSEC_PSK; - // Provider Type is user selectable, so enable all controls during init. - enable_psk_passphrase_ = true; - enable_user_cert_ = true; - enable_server_ca_cert_ = true; - enable_otp_ = true; - enable_group_name_ = true; - } - - // Initialize the title string ID used for the dialog. title_ = vpn ? IDS_OPTIONS_SETTINGS_JOIN_VPN : IDS_OPTIONS_SETTINGS_ADD_VPN; + // By default enable all controls. + enable_psk_passphrase_ = true; + enable_user_cert_ = true; + enable_server_ca_cert_ = true; + enable_otp_ = true; + enable_group_name_ = true; + // Server label and input. // Only provide Server name when configuring a new VPN. - if (!vpn) { - layout->StartRow(0, column_view_set_id); - layout->AddView(new views::Label(l10n_util::GetStringUTF16( + if (service_path_.empty()) { + layout_->StartRow(0, 0); + layout_->AddView(new views::Label(l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVER_HOSTNAME))); server_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT); server_textfield_->SetController(this); - layout->AddView(server_textfield_); - layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); + layout_->AddView(server_textfield_); + layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); } else { server_textfield_ = NULL; } // Service label and name or input. - layout->StartRow(0, column_view_set_id); - layout->AddView(new views::Label(l10n_util::GetStringUTF16( + layout_->StartRow(0, 0); + layout_->AddView(new views::Label(l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVICE_NAME))); - if (!vpn) { + if (service_path_.empty()) { service_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT); service_textfield_->SetController(this); - layout->AddView(service_textfield_); + layout_->AddView(service_textfield_); service_text_ = NULL; } else { - service_text_ = new views::Label(ASCIIToUTF16(vpn->name())); + service_text_ = new views::Label(); service_text_->SetHorizontalAlignment(gfx::ALIGN_LEFT); - layout->AddView(service_text_); + layout_->AddView(service_text_); service_textfield_ = NULL; } - layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); + layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); // Provider type label and select. - layout->StartRow(0, column_view_set_id); - layout->AddView(new views::Label(l10n_util::GetStringUTF16( + layout_->StartRow(0, 0); + layout_->AddView(new views::Label(l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PROVIDER_TYPE))); - if (!vpn) { + if (service_path_.empty()) { provider_type_combobox_model_.reset( new internal::ProviderTypeComboboxModel); provider_type_combobox_ = new views::Combobox( provider_type_combobox_model_.get()); provider_type_combobox_->set_listener(this); - layout->AddView(provider_type_combobox_); + layout_->AddView(provider_type_combobox_); provider_type_text_label_ = NULL; } else { - provider_type_text_label_ = - new views::Label(ProviderTypeToString(provider_type_)); + provider_type_text_label_ = new views::Label(); provider_type_text_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); - layout->AddView(provider_type_text_label_); + layout_->AddView(provider_type_text_label_); provider_type_combobox_ = NULL; } - layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); + layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); // PSK passphrase label, input and visible button. - if (enable_psk_passphrase_) { - layout->StartRow(0, column_view_set_id); - psk_passphrase_label_ = new views::Label(l10n_util::GetStringUTF16( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE)); - layout->AddView(psk_passphrase_label_); - bool has_psk_passphrase = vpn && !vpn->IsPSKPassphraseRequired(); - psk_passphrase_textfield_ = new PassphraseTextfield(has_psk_passphrase); - psk_passphrase_textfield_->SetController(this); - layout->AddView(psk_passphrase_textfield_); - layout->AddView( - new ControlledSettingIndicatorView(psk_passphrase_ui_data_)); - layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); - } else { - psk_passphrase_label_ = NULL; - psk_passphrase_textfield_ = NULL; - } + layout_->StartRow(0, 0); + psk_passphrase_label_ = new views::Label(l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE)); + layout_->AddView(psk_passphrase_label_); + psk_passphrase_textfield_ = new PassphraseTextfield(); + psk_passphrase_textfield_->SetController(this); + layout_->AddView(psk_passphrase_textfield_); + layout_->AddView( + new ControlledSettingIndicatorView(psk_passphrase_ui_data_)); + layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); // Server CA certificate - // Only provide Server CA when configuring a new VPN. - if (!vpn) { - layout->StartRow(0, column_view_set_id); - server_ca_cert_label_ = - new views::Label(l10n_util::GetStringUTF16( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA)); - layout->AddView(server_ca_cert_label_); + if (service_path_.empty()) { + layout_->StartRow(0, 0); + server_ca_cert_label_ = new views::Label(l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA)); + layout_->AddView(server_ca_cert_label_); server_ca_cert_combobox_model_.reset( new internal::VpnServerCACertComboboxModel()); server_ca_cert_combobox_ = new views::Combobox( server_ca_cert_combobox_model_.get()); - layout->AddView(server_ca_cert_combobox_); - layout->AddView(new ControlledSettingIndicatorView(ca_cert_ui_data_)); - layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); + layout_->AddView(server_ca_cert_combobox_); + layout_->AddView(new ControlledSettingIndicatorView(ca_cert_ui_data_)); + layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); } else { server_ca_cert_label_ = NULL; server_ca_cert_combobox_ = NULL; } // User certificate label and input. - if (enable_user_cert_) { - layout->StartRow(0, column_view_set_id); - user_cert_label_ = new views::Label(l10n_util::GetStringUTF16( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT)); - layout->AddView(user_cert_label_); - user_cert_combobox_model_.reset( - new internal::VpnUserCertComboboxModel()); - user_cert_combobox_ = new views::Combobox(user_cert_combobox_model_.get()); - user_cert_combobox_->set_listener(this); - layout->AddView(user_cert_combobox_); - layout->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_)); - layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); - } else { - user_cert_label_ = NULL; - user_cert_combobox_ = NULL; - } + layout_->StartRow(0, 0); + user_cert_label_ = new views::Label(l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT)); + layout_->AddView(user_cert_label_); + user_cert_combobox_model_.reset( + new internal::VpnUserCertComboboxModel()); + user_cert_combobox_ = new views::Combobox(user_cert_combobox_model_.get()); + user_cert_combobox_->set_listener(this); + layout_->AddView(user_cert_combobox_); + layout_->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_)); + layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); // Username label and input. - layout->StartRow(0, column_view_set_id); - layout->AddView(new views::Label(l10n_util::GetStringUTF16( + layout_->StartRow(0, 0); + layout_->AddView(new views::Label(l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USERNAME))); username_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT); username_textfield_->SetController(this); username_textfield_->SetEnabled(username_ui_data_.IsEditable()); - if (vpn && !vpn->username().empty()) - username_textfield_->SetText(UTF8ToUTF16(vpn->username())); - layout->AddView(username_textfield_); - layout->AddView(new ControlledSettingIndicatorView(username_ui_data_)); - layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); + layout_->AddView(username_textfield_); + layout_->AddView(new ControlledSettingIndicatorView(username_ui_data_)); + layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); // User passphrase label, input and visble button. - layout->StartRow(0, column_view_set_id); - layout->AddView(new views::Label(l10n_util::GetStringUTF16( + layout_->StartRow(0, 0); + layout_->AddView(new views::Label(l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_PASSPHRASE))); - bool has_user_passphrase = vpn && !vpn->IsUserPassphraseRequired(); - user_passphrase_textfield_ = new PassphraseTextfield(has_user_passphrase); + user_passphrase_textfield_ = new PassphraseTextfield(); user_passphrase_textfield_->SetController(this); user_passphrase_textfield_->SetEnabled(user_passphrase_ui_data_.IsEditable()); - layout->AddView(user_passphrase_textfield_); - layout->AddView(new ControlledSettingIndicatorView(user_passphrase_ui_data_)); - layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); + layout_->AddView(user_passphrase_textfield_); + layout_->AddView( + new ControlledSettingIndicatorView(user_passphrase_ui_data_)); + layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); // OTP label and input. - if (enable_otp_) { - layout->StartRow(0, column_view_set_id); - otp_label_ = new views::Label(l10n_util::GetStringUTF16( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_OTP)); - layout->AddView(otp_label_); - otp_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT); - otp_textfield_->SetController(this); - layout->AddView(otp_textfield_); - layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); - } else { - otp_label_ = NULL; - otp_textfield_ = NULL; - } + layout_->StartRow(0, 0); + otp_label_ = new views::Label(l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_OTP)); + layout_->AddView(otp_label_); + otp_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT); + otp_textfield_->SetController(this); + layout_->AddView(otp_textfield_); + layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); // Group Name label and input. - if (enable_group_name_) { - layout->StartRow(0, column_view_set_id); - group_name_label_ = new views::Label(l10n_util::GetStringUTF16( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_GROUP_NAME)); - layout->AddView(group_name_label_); - group_name_textfield_ = - new views::Textfield(views::Textfield::STYLE_DEFAULT); - group_name_textfield_->SetController(this); - if (vpn && !vpn->group_name().empty()) - group_name_textfield_->SetText(UTF8ToUTF16(vpn->group_name())); - layout->AddView(group_name_textfield_); - layout->AddView(new ControlledSettingIndicatorView(group_name_ui_data_)); - layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); - } else { - group_name_label_ = NULL; - group_name_textfield_ = NULL; - } + layout_->StartRow(0, 0); + group_name_label_ = new views::Label(l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_GROUP_NAME)); + layout_->AddView(group_name_label_); + group_name_textfield_ = + new views::Textfield(views::Textfield::STYLE_DEFAULT); + group_name_textfield_->SetController(this); + layout_->AddView(group_name_textfield_); + layout_->AddView(new ControlledSettingIndicatorView(group_name_ui_data_)); + layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); // Save credentials - layout->StartRow(0, column_view_set_id); + layout_->StartRow(0, 0); save_credentials_checkbox_ = new views::Checkbox( l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS)); save_credentials_checkbox_->SetEnabled( save_credentials_ui_data_.IsEditable()); - bool save_credentials = vpn ? vpn->save_credentials() : false; - save_credentials_checkbox_->SetChecked(save_credentials); - layout->SkipColumns(1); - layout->AddView(save_credentials_checkbox_); - layout->AddView( + layout_->SkipColumns(1); + layout_->AddView(save_credentials_checkbox_); + layout_->AddView( new ControlledSettingIndicatorView(save_credentials_ui_data_)); // Error label. - layout->StartRow(0, column_view_set_id); - layout->SkipColumns(1); + layout_->StartRow(0, 0); + layout_->SkipColumns(1); error_label_ = new views::Label(); error_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); error_label_->SetEnabledColor(SK_ColorRED); - layout->AddView(error_label_); + layout_->AddView(error_label_); // Set or hide the UI, update comboboxes and error labels. Refresh(); + + if (vpn) { + NetworkHandler::Get()->network_configuration_handler()->GetProperties( + service_path_, + base::Bind(&VPNConfigView::InitFromProperties, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&VPNConfigView::GetPropertiesError, + weak_ptr_factory_.GetWeakPtr())); + } } -void VPNConfigView::Refresh() { - NetworkLibrary* cros = NetworkLibrary::Get(); +void VPNConfigView::InitFromProperties( + const std::string& service_path, + const base::DictionaryValue& service_properties) { + const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()-> + GetNetworkState(service_path); + if (!vpn) { + NET_LOG_ERROR("Shill Error getting properties VpnConfigView", service_path); + return; + } + + std::string provider_type, server_hostname, username, group_name; + bool psk_passphrase_required = false; + const base::DictionaryValue* provider_properties; + if (service_properties.GetDictionaryWithoutPathExpansion( + flimflam::kProviderProperty, &provider_properties)) { + provider_properties->GetStringWithoutPathExpansion( + flimflam::kTypeProperty, &provider_type); + provider_properties->GetStringWithoutPathExpansion( + flimflam::kHostProperty, &server_hostname); + } + if (provider_type == flimflam::kProviderL2tpIpsec) { + provider_properties->GetStringWithoutPathExpansion( + flimflam::kL2tpIpsecClientCertIdProperty, &client_cert_id_); + ca_cert_pem_ = GetPemFromDictionary( + provider_properties, shill::kL2tpIpsecCaCertPemProperty); + provider_properties->GetBooleanWithoutPathExpansion( + flimflam::kL2tpIpsecPskRequiredProperty, &psk_passphrase_required); + provider_properties->GetStringWithoutPathExpansion( + flimflam::kL2tpIpsecUserProperty, &username); + provider_properties->GetStringWithoutPathExpansion( + shill::kL2tpIpsecTunnelGroupProperty, &group_name); + } else if (provider_type == flimflam::kProviderOpenVpn) { + provider_properties->GetStringWithoutPathExpansion( + flimflam::kOpenVPNClientCertIdProperty, &client_cert_id_); + ca_cert_pem_ = GetPemFromDictionary( + provider_properties, shill::kOpenVPNCaCertPemProperty); + provider_properties->GetStringWithoutPathExpansion( + flimflam::kOpenVPNUserProperty, &username); + } + bool save_credentials = false; + service_properties.GetBooleanWithoutPathExpansion( + flimflam::kSaveCredentialsProperty, &save_credentials); + + provider_type_index_ = ProviderTypeToIndex(provider_type, client_cert_id_); + + if (service_text_) + service_text_->SetText(ASCIIToUTF16(vpn->name())); + if (provider_type_text_label_) + provider_type_text_label_->SetText( + ProviderTypeIndexToString(provider_type_index_)); + + if (server_textfield_ && !server_hostname.empty()) + server_textfield_->SetText(UTF8ToUTF16(server_hostname)); + if (username_textfield_ && !username.empty()) + username_textfield_->SetText(UTF8ToUTF16(username)); + if (group_name_textfield_ && !group_name.empty()) + group_name_textfield_->SetText(UTF8ToUTF16(group_name)); + if (psk_passphrase_textfield_) + psk_passphrase_textfield_->SetShowFake(!psk_passphrase_required); + if (save_credentials_checkbox_) + save_credentials_checkbox_->SetChecked(save_credentials); + + Refresh(); +} + +void VPNConfigView::ParseUIProperties(const NetworkState* vpn) { + std::string type_dict_name = + ProviderTypeIndexToONCDictKey(provider_type_index_); + if (provider_type_index_ == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK) { + ParseVPNUIProperty(vpn, type_dict_name, onc::ipsec::kServerCARef, + &ca_cert_ui_data_); + ParseVPNUIProperty(vpn, type_dict_name, onc::ipsec::kPSK, + &psk_passphrase_ui_data_); + ParseVPNUIProperty(vpn, type_dict_name, onc::ipsec::kGroup, + &group_name_ui_data_); + } else if (provider_type_index_ == PROVIDER_TYPE_INDEX_OPEN_VPN) { + ParseVPNUIProperty(vpn, type_dict_name, onc::openvpn::kServerCARef, + &ca_cert_ui_data_); + } + ParseVPNUIProperty(vpn, type_dict_name, onc::vpn::kClientCertRef, + &user_cert_ui_data_); + + const std::string credentials_dict_name( + provider_type_index_ == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK ? + onc::vpn::kL2TP : type_dict_name); + ParseVPNUIProperty(vpn, credentials_dict_name, onc::vpn::kUsername, + &username_ui_data_); + ParseVPNUIProperty(vpn, credentials_dict_name, onc::vpn::kPassword, + &user_passphrase_ui_data_); + ParseVPNUIProperty(vpn, credentials_dict_name, onc::vpn::kSaveCredentials, + &save_credentials_ui_data_); +} + +void VPNConfigView::GetPropertiesError( + const std::string& error_name, + scoped_ptr<base::DictionaryValue> error_data) { + NET_LOG_ERROR("Shill Error from VpnConfigView: " + error_name, ""); +} + +void VPNConfigView::SetConfigProperties( + base::DictionaryValue* properties) { + int provider_type_index = GetProviderTypeIndex(); + std::string user_passphrase = GetUserPassphrase(); + std::string user_name = GetUsername(); + std::string group_name = GetGroupName(); + switch (provider_type_index) { + case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK: { + std::string psk_passphrase = GetPSKPassphrase(); + if (!psk_passphrase.empty()) { + properties->SetStringWithoutPathExpansion( + flimflam::kL2tpIpsecPskProperty, GetPSKPassphrase()); + } + if (!group_name.empty()) { + properties->SetStringWithoutPathExpansion( + shill::kL2tpIpsecTunnelGroupProperty, group_name); + } + if (!user_name.empty()) { + properties->SetStringWithoutPathExpansion( + flimflam::kL2tpIpsecUserProperty, user_name); + } + if (!user_passphrase.empty()) { + properties->SetStringWithoutPathExpansion( + flimflam::kL2tpIpsecPasswordProperty, user_passphrase); + } + break; + } + case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT: { + std::string ca_cert_pem = GetServerCACertPEM(); + if (!ca_cert_pem.empty()) { + properties->SetStringWithoutPathExpansion( + shill::kL2tpIpsecCaCertPemProperty, ca_cert_pem); + } + properties->SetStringWithoutPathExpansion( + flimflam::kL2tpIpsecClientCertIdProperty, GetUserCertID()); + if (!group_name.empty()) { + properties->SetStringWithoutPathExpansion( + shill::kL2tpIpsecTunnelGroupProperty, GetGroupName()); + } + if (!user_name.empty()) { + properties->SetStringWithoutPathExpansion( + flimflam::kL2tpIpsecUserProperty, user_name); + } + if (!user_passphrase.empty()) { + properties->SetStringWithoutPathExpansion( + flimflam::kL2tpIpsecPasswordProperty, user_passphrase); + } + break; + } + case PROVIDER_TYPE_INDEX_OPEN_VPN: { + std::string ca_cert_pem = GetServerCACertPEM(); + if (!ca_cert_pem.empty()) { + base::ListValue* pem_list = new base::ListValue; + pem_list->AppendString(GetServerCACertPEM()); + properties->SetWithoutPathExpansion( + shill::kOpenVPNCaCertPemProperty, pem_list); + } + properties->SetStringWithoutPathExpansion( + flimflam::kOpenVPNClientCertIdProperty, GetUserCertID()); + properties->SetStringWithoutPathExpansion( + flimflam::kOpenVPNUserProperty, GetUsername()); + if (!user_passphrase.empty()) { + properties->SetStringWithoutPathExpansion( + flimflam::kOpenVPNPasswordProperty, user_passphrase); + } + std::string otp = GetOTP(); + if (!otp.empty()) { + properties->SetStringWithoutPathExpansion( + flimflam::kOpenVPNOTPProperty, otp); + } + break; + } + case PROVIDER_TYPE_INDEX_MAX: + NOTREACHED(); + break; + } + properties->SetBooleanWithoutPathExpansion( + flimflam::kSaveCredentialsProperty, GetSaveCredentials()); +} +void VPNConfigView::Refresh() { UpdateControls(); // Set certificate combo boxes. - VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_); if (server_ca_cert_combobox_) { server_ca_cert_combobox_->ModelChanged(); - if (enable_server_ca_cert_ && - (vpn && !vpn->ca_cert_pem().empty())) { + if (enable_server_ca_cert_ && !ca_cert_pem_.empty()) { // Select the current server CA certificate in the combobox. int cert_index = CertLibrary::Get()->GetCertIndexByPEM( - CertLibrary::CERT_TYPE_SERVER_CA, vpn->ca_cert_pem()); + CertLibrary::CERT_TYPE_SERVER_CA, ca_cert_pem_); if (cert_index >= 0) { // Skip item for "Default" server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index); @@ -740,10 +891,9 @@ void VPNConfigView::Refresh() { if (user_cert_combobox_) { user_cert_combobox_->ModelChanged(); - if (enable_user_cert_ && - (vpn && !vpn->client_cert_id().empty())) { + if (enable_user_cert_ && !client_cert_id_.empty()) { int cert_index = CertLibrary::Get()->GetCertIndexByPkcs11Id( - CertLibrary::CERT_TYPE_USER, vpn->client_cert_id()); + CertLibrary::CERT_TYPE_USER, client_cert_id_); if (cert_index >= 0) user_cert_combobox_->SetSelectedIndex(cert_index); else @@ -757,30 +907,23 @@ void VPNConfigView::Refresh() { } void VPNConfigView::UpdateControlsToEnable() { - // Set which controls are enabled. enable_psk_passphrase_ = false; enable_user_cert_ = false; enable_server_ca_cert_ = false; enable_otp_ = false; enable_group_name_ = false; - switch (provider_type_) { - case PROVIDER_TYPE_L2TP_IPSEC_PSK: - enable_psk_passphrase_ = true; - enable_group_name_ = true; - break; - case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: - enable_server_ca_cert_ = true; - enable_user_cert_ = HaveUserCerts(); - enable_group_name_ = true; - break; - case PROVIDER_TYPE_OPEN_VPN: - enable_server_ca_cert_ = true; - enable_user_cert_ = HaveUserCerts(); - enable_otp_ = true; - break; - default: - NOTREACHED(); - break; + int provider_type_index = GetProviderTypeIndex(); + if (provider_type_index == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK) { + enable_psk_passphrase_ = true; + enable_group_name_ = true; + } else if (provider_type_index == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT) { + enable_server_ca_cert_ = true; + enable_user_cert_ = HaveUserCerts(); + enable_group_name_ = true; + } else { // PROVIDER_TYPE_INDEX_OPEN_VPN (default) + enable_server_ca_cert_ = true; + enable_user_cert_ = HaveUserCerts(); + enable_otp_ = true; } } @@ -818,33 +961,28 @@ void VPNConfigView::UpdateControls() { } void VPNConfigView::UpdateErrorLabel() { - NetworkLibrary* cros = NetworkLibrary::Get(); - // Error message. - std::string error_msg; - if (UserCertRequired() && CertLibrary::Get()->CertificatesLoaded()) { + string16 error_msg; + bool cert_required = + GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT; + if (cert_required && CertLibrary::Get()->CertificatesLoaded()) { if (!HaveUserCerts()) { - error_msg = l10n_util::GetStringUTF8( + error_msg = l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT); } else if (!IsUserCertValid()) { - error_msg = l10n_util::GetStringUTF8( + error_msg = l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED); } } if (error_msg.empty() && !service_path_.empty()) { // TODO(kuan): differentiate between bad psk and user passphrases. - VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_); - if (vpn && vpn->failed()) { - if (vpn->error() == ERROR_BAD_PASSPHRASE) { - error_msg = l10n_util::GetStringUTF8( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE); - } else { - error_msg = vpn->GetErrorString(); - } - } + const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()-> + GetNetworkState(service_path_); + if (vpn && vpn->connection_state() == flimflam::kStateFailure) + error_msg = ash::network_connect::ErrorString(vpn->error()); } if (!error_msg.empty()) { - error_label_->SetText(UTF8ToUTF16(error_msg)); + error_label_->SetText(error_msg); error_label_->SetVisible(true); } else { error_label_->SetVisible(false); @@ -855,10 +993,6 @@ void VPNConfigView::UpdateCanLogin() { parent_->GetDialogClientView()->UpdateDialogButtons(); } -bool VPNConfigView::UserCertRequired() const { - return provider_type_ == PROVIDER_TYPE_L2TP_IPSEC_USER_CERT; -} - bool VPNConfigView::HaveUserCerts() const { return CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER) > 0; } @@ -896,15 +1030,16 @@ const std::string VPNConfigView::GetPassphraseFromField( return textfield->GetPassphrase(); } -void VPNConfigView::ParseVPNUIProperty(NetworkPropertyUIData* property_ui_data, - Network* network, - const std::string& dict_key, - const std::string& key) { +void VPNConfigView::ParseVPNUIProperty( + const NetworkState* network, + const std::string& dict_key, + const std::string& key, + NetworkPropertyUIData* property_ui_data) { onc::ONCSource onc_source = onc::ONC_SOURCE_NONE; const base::DictionaryValue* onc = - NetworkConfigView::FindPolicyForActiveUser(network, &onc_source); + network_connect::FindPolicyForActiveUser(network, &onc_source); - VLOG_IF(1, !onc) << "No ONC found for VPN network " << network->unique_id(); + VLOG_IF(1, !onc) << "No ONC found for VPN network " << network->guid(); property_ui_data->ParseOncProperty( onc_source, onc, diff --git a/chrome/browser/chromeos/options/vpn_config_view.h b/chrome/browser/chromeos/options/vpn_config_view.h index cb5f7ce..24c1a5a 100644 --- a/chrome/browser/chromeos/options/vpn_config_view.h +++ b/chrome/browser/chromeos/options/vpn_config_view.h @@ -18,13 +18,20 @@ #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/view.h" +namespace base { +class DictionaryValue; +} + namespace views { class Checkbox; +class GridLayout; class Label; } namespace chromeos { +class NetworkState; + namespace internal { class ProviderTypeComboboxModel; class VpnServerCACertComboboxModel; @@ -38,8 +45,7 @@ class VPNConfigView : public ChildNetworkConfigView, public views::ComboboxListener, public CertLibrary::Observer { public: - VPNConfigView(NetworkConfigView* parent, VirtualNetwork* vpn); - explicit VPNConfigView(NetworkConfigView* parent); + VPNConfigView(NetworkConfigView* parent, const std::string& service_path); virtual ~VPNConfigView(); // views::TextfieldController: @@ -68,7 +74,17 @@ class VPNConfigView : public ChildNetworkConfigView, private: // Initializes data members and create UI controls. - void Init(VirtualNetwork* vpn); + void Init(); + + // Callback to initialize fields from uncached network properties. + void InitFromProperties(const std::string& service_path, + const base::DictionaryValue& dictionary); + void ParseUIProperties(const NetworkState* vpn); + void GetPropertiesError(const std::string& error_name, + scoped_ptr<base::DictionaryValue> error_data); + + // Helper function to set configurable properties. + void SetConfigProperties(base::DictionaryValue* properties); // Set and update all control values. void Refresh(); @@ -81,9 +97,6 @@ class VPNConfigView : public ChildNetworkConfigView, // Update state of the Login button. void UpdateCanLogin(); - // Returns true if the provider type requires a user certificate. - bool UserCertRequired() const; - // Returns true if there is at least one user certificate installed. bool HaveUserCerts() const; @@ -109,22 +122,21 @@ class VPNConfigView : public ChildNetworkConfigView, const std::string GetServerCACertPEM() const; const std::string GetUserCertID() const; bool GetSaveCredentials() const; + int GetProviderTypeIndex() const; + std::string GetProviderTypeString() const; // Parses a VPN UI |property| from the given |network|. |key| is the property // name within the type-specific VPN subdictionary named |dict_key|. - void ParseVPNUIProperty(NetworkPropertyUIData* property_ui_data, - Network* network, + void ParseVPNUIProperty(const NetworkState* network, const std::string& dict_key, - const std::string& key); + const std::string& key, + NetworkPropertyUIData* property_ui_data); - std::string server_hostname_; string16 service_name_from_server_; bool service_text_modified_; // Initialized in Init(): - ProviderType provider_type_; - bool enable_psk_passphrase_; bool enable_user_cert_; bool enable_server_ca_cert_; @@ -141,6 +153,7 @@ class VPNConfigView : public ChildNetworkConfigView, int title_; + views::GridLayout* layout_; views::Textfield* server_textfield_; views::Label* service_text_; views::Textfield* service_textfield_; @@ -165,6 +178,13 @@ class VPNConfigView : public ChildNetworkConfigView, views::Checkbox* save_credentials_checkbox_; views::Label* error_label_; + // Cached VPN properties, only set when configuring an existing network. + int provider_type_index_; + std::string ca_cert_pem_; + std::string client_cert_id_; + + base::WeakPtrFactory<VPNConfigView> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(VPNConfigView); }; diff --git a/chrome/browser/chromeos/options/wifi_config_view.cc b/chrome/browser/chromeos/options/wifi_config_view.cc index 211f728..e047850 100644 --- a/chrome/browser/chromeos/options/wifi_config_view.cc +++ b/chrome/browser/chromeos/options/wifi_config_view.cc @@ -4,19 +4,26 @@ #include "chrome/browser/chromeos/options/wifi_config_view.h" +#include "ash/system/chromeos/network/network_connect.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/chromeos/cros/network_library.h" #include "chrome/browser/chromeos/enrollment_dialog_view.h" +#include "chrome/browser/chromeos/options/network_connect.h" #include "chrome/browser/profiles/profile_manager.h" #include "chromeos/login/login_state.h" +#include "chromeos/network/network_configuration_handler.h" +#include "chromeos/network/network_event_log.h" +#include "chromeos/network/network_handler.h" +#include "chromeos/network/network_state.h" +#include "chromeos/network/network_state_handler.h" #include "chromeos/network/network_ui_data.h" #include "chromeos/network/onc/onc_constants.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "grit/theme_resources.h" +#include "third_party/cros_system_api/dbus/service_constants.h" #include "ui/base/events/event.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -34,11 +41,6 @@ namespace chromeos { namespace { -// Returns true if network is known to require 802.1x. -bool Is8021x(const WifiNetwork* wifi) { - return wifi && wifi->encrypted() && wifi->encryption() == SECURITY_8021X; -} - // Combobox that supports a preferred width. Used by Server CA combobox // because the strings inside it are too wide. class ComboboxWithWidth : public views::Combobox { @@ -85,6 +87,12 @@ enum Phase2AuthComboboxIndex { PHASE_2_AUTH_INDEX_COUNT = 6 }; +void ShillError(const std::string& function, + const std::string& error_name, + scoped_ptr<base::DictionaryValue> error_data) { + NET_LOG_ERROR("Shill Error from WifiConfigView: " + error_name, function); +} + } // namespace namespace internal { @@ -322,8 +330,10 @@ string16 UserCertComboboxModel::GetItemAt(int index) { } // namespace internal -WifiConfigView::WifiConfigView(NetworkConfigView* parent, WifiNetwork* wifi) - : ChildNetworkConfigView(parent, wifi), +WifiConfigView::WifiConfigView(NetworkConfigView* parent, + const std::string& service_path, + bool show_8021x) + : ChildNetworkConfigView(parent, service_path), ssid_textfield_(NULL), eap_method_combobox_(NULL), phase_2_auth_label_(NULL), @@ -343,33 +353,9 @@ WifiConfigView::WifiConfigView(NetworkConfigView* parent, WifiNetwork* wifi) passphrase_label_(NULL), passphrase_textfield_(NULL), passphrase_visible_button_(NULL), - error_label_(NULL) { - Init(wifi, Is8021x(wifi)); -} - -WifiConfigView::WifiConfigView(NetworkConfigView* parent, bool show_8021x) - : ChildNetworkConfigView(parent), - ssid_textfield_(NULL), - eap_method_combobox_(NULL), - phase_2_auth_label_(NULL), - phase_2_auth_combobox_(NULL), - user_cert_label_(NULL), - user_cert_combobox_(NULL), - server_ca_cert_label_(NULL), - server_ca_cert_combobox_(NULL), - identity_label_(NULL), - identity_textfield_(NULL), - identity_anonymous_label_(NULL), - identity_anonymous_textfield_(NULL), - save_credentials_checkbox_(NULL), - share_network_checkbox_(NULL), - shared_network_label_(NULL), - security_combobox_(NULL), - passphrase_label_(NULL), - passphrase_textfield_(NULL), - passphrase_visible_button_(NULL), - error_label_(NULL) { - Init(NULL, show_8021x); + error_label_(NULL), + weak_ptr_factory_(this) { + Init(show_8021x); } WifiConfigView::~WifiConfigView() { @@ -541,8 +527,8 @@ void WifiConfigView::RefreshShareCheckbox() { // user certificates are enabled. share_network_checkbox_->SetEnabled(false); share_network_checkbox_->SetChecked(false); - } else if (!LoginState::Get()->IsUserLoggedIn()) { - // If not logged in, networks must be shared. + } else if (!LoginState::Get()->IsUserAuthenticated()) { + // If not logged in as an authenticated user, networks must be shared. share_network_checkbox_->SetEnabled(false); share_network_checkbox_->SetChecked(true); } else { @@ -552,47 +538,29 @@ void WifiConfigView::RefreshShareCheckbox() { } void WifiConfigView::UpdateErrorLabel() { - std::string error_msg; + base::string16 error_msg; if (UserCertRequired() && CertLibrary::Get()->CertificatesLoaded()) { if (!HaveUserCerts()) { - if (!LoginState::Get()->IsUserLoggedIn()) { - error_msg = l10n_util::GetStringUTF8( + if (!LoginState::Get()->IsUserAuthenticated()) { + error_msg = l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_LOGIN_FOR_USER_CERT); } else { - error_msg = l10n_util::GetStringUTF8( + error_msg = l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT); } } else if (!IsUserCertValid()) { - error_msg = l10n_util::GetStringUTF8( + error_msg = l10n_util::GetStringUTF16( IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED); } } if (error_msg.empty() && !service_path_.empty()) { - NetworkLibrary* cros = NetworkLibrary::Get(); - const WifiNetwork* wifi = cros->FindWifiNetworkByPath(service_path_); - if (wifi && wifi->failed()) { - bool passphrase_empty = wifi->GetPassphrase().empty(); - switch (wifi->error()) { - case ERROR_BAD_PASSPHRASE: - if (!passphrase_empty) { - error_msg = l10n_util::GetStringUTF8( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE); - } - break; - case ERROR_BAD_WEPKEY: - if (!passphrase_empty) { - error_msg = l10n_util::GetStringUTF8( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_WEPKEY); - } - break; - default: - error_msg = wifi->GetErrorString(); - break; - } - } + const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()-> + GetNetworkState(service_path_); + if (wifi && wifi->connection_state() == flimflam::kStateFailure) + error_msg = ash::network_connect::ErrorString(wifi->error()); } if (!error_msg.empty()) { - error_label_->SetText(UTF8ToUTF16(error_msg)); + error_label_->SetText(error_msg); error_label_->SetVisible(true); } else { error_label_->SetVisible(false); @@ -651,83 +619,74 @@ void WifiConfigView::OnCertificatesLoaded(bool initial_load) { } bool WifiConfigView::Login() { - NetworkLibrary* cros = NetworkLibrary::Get(); + const bool share_default = true; if (service_path_.empty()) { - const bool share_default = true; // share networks by default + // Set configuration properties. + base::DictionaryValue properties; + properties.SetStringWithoutPathExpansion( + flimflam::kTypeProperty, flimflam::kTypeWifi); + properties.SetStringWithoutPathExpansion( + flimflam::kSSIDProperty, GetSsid()); + properties.SetStringWithoutPathExpansion( + flimflam::kModeProperty, flimflam::kModeManaged); + properties.SetBooleanWithoutPathExpansion( + flimflam::kSaveCredentialsProperty, GetSaveCredentials()); + std::string security = flimflam::kSecurityNone; if (!eap_method_combobox_) { // Hidden ordinary Wi-Fi connection. - ConnectionSecurity security = SECURITY_UNKNOWN; switch (security_combobox_->selected_index()) { case SECURITY_INDEX_NONE: - security = SECURITY_NONE; + security = flimflam::kSecurityNone; break; case SECURITY_INDEX_WEP: - security = SECURITY_WEP; + security = flimflam::kSecurityWep; break; case SECURITY_INDEX_PSK: - security = SECURITY_PSK; + security = flimflam::kSecurityPsk; break; } - cros->ConnectToUnconfiguredWifiNetwork( - GetSsid(), - security, - GetPassphrase(), - NULL, - GetSaveCredentials(), - GetShareNetwork(share_default)); + std::string passphrase = GetPassphrase(); + if (!passphrase.empty()) { + properties.SetStringWithoutPathExpansion( + flimflam::kPassphraseProperty, GetPassphrase()); + } } else { // Hidden 802.1X EAP Wi-Fi connection. - chromeos::NetworkLibrary::EAPConfigData config_data; - config_data.method = GetEapMethod(); - config_data.auth = GetEapPhase2Auth(); - config_data.server_ca_cert_pem = GetEapServerCaCertPEM(); - config_data.use_system_cas = GetEapUseSystemCas(); - config_data.client_cert_pkcs11_id = GetEapClientCertPkcs11Id(); - config_data.identity = GetEapIdentity(); - config_data.anonymous_identity = GetEapAnonymousIdentity(); - cros->ConnectToUnconfiguredWifiNetwork( - GetSsid(), - SECURITY_8021X, - GetPassphrase(), - &config_data, - GetSaveCredentials(), - GetShareNetwork(share_default)); + security = flimflam::kSecurity8021x; + SetEapProperties(&properties); } + properties.SetStringWithoutPathExpansion( + flimflam::kSecurityProperty, security); + + // Configure and connect to network. + bool shared = GetShareNetwork(share_default); + ash::network_connect::CreateConfigurationAndConnect(&properties, shared); } else { - WifiNetwork* wifi = cros->FindWifiNetworkByPath(service_path_); + const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()-> + GetNetworkState(service_path_); if (!wifi) { // Shill no longer knows about this wifi network (edge case). - // TODO(stevenjb): Add a notification (chromium-os13225). - LOG(WARNING) << "Wifi network: " << service_path_ << " no longer exists."; - return true; + // TODO(stevenjb): Add notification for this. + NET_LOG_ERROR("Network not found", service_path_); + return true; // Close dialog } + base::DictionaryValue properties; if (eap_method_combobox_) { // Visible 802.1X EAP Wi-Fi connection. - EAPMethod method = GetEapMethod(); - DCHECK(method != EAP_METHOD_UNKNOWN); - wifi->SetEAPMethod(method); - wifi->SetEAPPhase2Auth(GetEapPhase2Auth()); - wifi->SetEAPServerCaCertPEM(GetEapServerCaCertPEM()); - wifi->SetEAPUseSystemCAs(GetEapUseSystemCas()); - wifi->SetEAPClientCertPkcs11Id(GetEapClientCertPkcs11Id()); - wifi->SetEAPIdentity(GetEapIdentity()); - wifi->SetEAPAnonymousIdentity(GetEapAnonymousIdentity()); - wifi->SetEAPPassphrase(GetPassphrase()); - wifi->SetSaveCredentials(GetSaveCredentials()); + SetEapProperties(&properties); + properties.SetBooleanWithoutPathExpansion( + flimflam::kSaveCredentialsProperty, GetSaveCredentials()); } else { // Visible ordinary Wi-Fi connection. const std::string passphrase = GetPassphrase(); - if (passphrase != wifi->passphrase()) - wifi->SetPassphrase(passphrase); + if (!passphrase.empty()) { + properties.SetStringWithoutPathExpansion( + flimflam::kPassphraseProperty, passphrase); + } } - bool share_default = (wifi->profile_type() != PROFILE_USER); - wifi->SetEnrollmentDelegate( - CreateEnrollmentDelegate(GetWidget()->GetNativeWindow(), - wifi->name(), - ProfileManager::GetLastUsedProfile())); - cros->ConnectToWifiNetwork(wifi, GetShareNetwork(share_default)); - // Connection failures are responsible for updating the UI, including - // reopening dialogs. + bool share_network = GetShareNetwork(share_default); + ash::network_connect::ConfigureNetworkAndConnect( + service_path_, properties, share_network); } return true; // dialog will be closed } @@ -760,41 +719,42 @@ bool WifiConfigView::GetShareNetwork(bool share_default) const { return share_network_checkbox_->checked(); } -EAPMethod WifiConfigView::GetEapMethod() const { +std::string WifiConfigView::GetEapMethod() const { DCHECK(eap_method_combobox_); switch (eap_method_combobox_->selected_index()) { - case EAP_METHOD_INDEX_NONE: - return EAP_METHOD_UNKNOWN; case EAP_METHOD_INDEX_PEAP: - return EAP_METHOD_PEAP; + return flimflam::kEapMethodPEAP; case EAP_METHOD_INDEX_TLS: - return EAP_METHOD_TLS; + return flimflam::kEapMethodTLS; case EAP_METHOD_INDEX_TTLS: - return EAP_METHOD_TTLS; + return flimflam::kEapMethodTTLS; case EAP_METHOD_INDEX_LEAP: - return EAP_METHOD_LEAP; + return flimflam::kEapMethodLEAP; + case EAP_METHOD_INDEX_NONE: default: - return EAP_METHOD_UNKNOWN; + return ""; } } -EAPPhase2Auth WifiConfigView::GetEapPhase2Auth() const { +std::string WifiConfigView::GetEapPhase2Auth() const { DCHECK(phase_2_auth_combobox_); + bool is_peap = (GetEapMethod() == flimflam::kEapMethodPEAP); switch (phase_2_auth_combobox_->selected_index()) { - case PHASE_2_AUTH_INDEX_AUTO: - return EAP_PHASE_2_AUTH_AUTO; case PHASE_2_AUTH_INDEX_MD5: - return EAP_PHASE_2_AUTH_MD5; + return is_peap ? flimflam::kEapPhase2AuthPEAPMD5 + : flimflam::kEapPhase2AuthTTLSMD5; case PHASE_2_AUTH_INDEX_MSCHAPV2: - return EAP_PHASE_2_AUTH_MSCHAPV2; + return is_peap ? flimflam::kEapPhase2AuthPEAPMSCHAPV2 + : flimflam::kEapPhase2AuthTTLSMSCHAPV2; case PHASE_2_AUTH_INDEX_MSCHAP: - return EAP_PHASE_2_AUTH_MSCHAP; + return flimflam::kEapPhase2AuthTTLSMSCHAP; case PHASE_2_AUTH_INDEX_PAP: - return EAP_PHASE_2_AUTH_PAP; + return flimflam::kEapPhase2AuthTTLSPAP; case PHASE_2_AUTH_INDEX_CHAP: - return EAP_PHASE_2_AUTH_CHAP; + return flimflam::kEapPhase2AuthTTLSCHAP; + case PHASE_2_AUTH_INDEX_AUTO: default: - return EAP_PHASE_2_AUTH_AUTO; + return ""; } } @@ -842,6 +802,34 @@ std::string WifiConfigView::GetEapAnonymousIdentity() const { return UTF16ToUTF8(identity_anonymous_textfield_->text()); } +void WifiConfigView::SetEapProperties(base::DictionaryValue* properties) { + properties->SetStringWithoutPathExpansion( + flimflam::kEapIdentityProperty, GetEapIdentity()); + properties->SetStringWithoutPathExpansion( + flimflam::kEapMethodProperty, GetEapMethod()); + properties->SetStringWithoutPathExpansion( + flimflam::kEapPhase2AuthProperty, GetEapPhase2Auth()); + properties->SetStringWithoutPathExpansion( + flimflam::kEapAnonymousIdentityProperty, GetEapAnonymousIdentity()); + + // shill requires both CertID and KeyID for TLS connections, despite + // the fact that by convention they are the same ID. + properties->SetStringWithoutPathExpansion( + flimflam::kEapCertIdProperty, GetEapClientCertPkcs11Id()); + properties->SetStringWithoutPathExpansion( + flimflam::kEapKeyIdProperty, GetEapClientCertPkcs11Id()); + + properties->SetBooleanWithoutPathExpansion( + flimflam::kEapUseSystemCasProperty, GetEapUseSystemCas()); + properties->SetStringWithoutPathExpansion( + flimflam::kEapPasswordProperty, GetPassphrase()); + + base::ListValue* pem_list = new base::ListValue; + pem_list->AppendString(GetEapServerCaCertPEM()); + properties->SetWithoutPathExpansion( + shill::kEapCaCertPemProperty, pem_list); +} + void WifiConfigView::Cancel() { } @@ -851,8 +839,13 @@ void WifiConfigView::Cancel() { // If we are creating the "Join other network..." dialog, we will allow user // to enter the data. And if they select the 802.1x encryption, we will show // the 802.1x fields. -void WifiConfigView::Init(WifiNetwork* wifi, bool show_8021x) { +void WifiConfigView::Init(bool show_8021x) { + const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()-> + GetNetworkState(service_path_); if (wifi) { + DCHECK(wifi->type() == flimflam::kTypeWifi); + if (wifi->security() == flimflam::kSecurity8021x) + show_8021x = true; ParseWiFiEAPUIProperty(&eap_method_ui_data_, wifi, onc::eap::kOuter); ParseWiFiEAPUIProperty(&phase_2_auth_ui_data_, wifi, onc::eap::kInner); ParseWiFiEAPUIProperty(&user_cert_ui_data_, wifi, onc::eap::kClientCertRef); @@ -1007,8 +1000,6 @@ void WifiConfigView::Init(WifiNetwork* wifi, bool show_8021x) { views::Textfield::STYLE_DEFAULT); identity_textfield_->SetAccessibleName(identity_label_text); identity_textfield_->SetController(this); - if (wifi && !wifi->identity().empty()) - identity_textfield_->SetText(UTF8ToUTF16(wifi->identity())); identity_textfield_->SetEnabled(identity_ui_data_.IsEditable()); layout->AddView(identity_textfield_); layout->AddView(new ControlledSettingIndicatorView(identity_ui_data_)); @@ -1024,8 +1015,6 @@ void WifiConfigView::Init(WifiNetwork* wifi, bool show_8021x) { passphrase_textfield_ = new views::Textfield( views::Textfield::STYLE_OBSCURED); passphrase_textfield_->SetController(this); - if (wifi && !wifi->GetPassphrase().empty()) - passphrase_textfield_->SetText(UTF8ToUTF16(wifi->GetPassphrase())); // Disable passphrase input initially for other network. passphrase_label_->SetEnabled(wifi != NULL); passphrase_textfield_->SetEnabled(wifi && passphrase_ui_data_.IsEditable()); @@ -1102,10 +1091,7 @@ void WifiConfigView::Init(WifiNetwork* wifi, bool show_8021x) { } // Share network - if (!wifi || - (wifi->profile_type() == PROFILE_NONE && - wifi->IsPassphraseRequired() && - !wifi->RequiresUserProfile())) { + if (!wifi || wifi->profile_path().empty()) { layout->StartRow(0, column_view_set_id); share_network_checkbox_ = new views::Checkbox( l10n_util::GetStringUTF16( @@ -1125,112 +1111,132 @@ void WifiConfigView::Init(WifiNetwork* wifi, bool show_8021x) { // Initialize the field and checkbox values. - // After creating the fields, we set the values. Fields need to be created - // first because RefreshEapFields() will enable/disable them as appropriate. - if (show_8021x) { - EAPMethod eap_method = (wifi ? wifi->eap_method() : EAP_METHOD_UNKNOWN); - switch (eap_method) { - case EAP_METHOD_PEAP: - eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_PEAP); - break; - case EAP_METHOD_TTLS: - eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TTLS); - break; - case EAP_METHOD_TLS: - eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TLS); - break; - case EAP_METHOD_LEAP: - eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_LEAP); - break; - default: - break; - } + if (!wifi && show_8021x) RefreshEapFields(); - // Phase 2 authentication and anonymous identity. - if (Phase2AuthActive()) { - EAPPhase2Auth eap_phase_2_auth = - (wifi ? wifi->eap_phase_2_auth() : EAP_PHASE_2_AUTH_AUTO); - switch (eap_phase_2_auth) { - case EAP_PHASE_2_AUTH_MD5: - phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MD5); - break; - case EAP_PHASE_2_AUTH_MSCHAPV2: - phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAPV2); - break; - case EAP_PHASE_2_AUTH_MSCHAP: - phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAP); - break; - case EAP_PHASE_2_AUTH_PAP: - phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_PAP); - break; - case EAP_PHASE_2_AUTH_CHAP: - phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_CHAP); - break; - default: - break; - } + RefreshShareCheckbox(); + UpdateErrorLabel(); - const std::string& eap_anonymous_identity = - (wifi ? wifi->eap_anonymous_identity() : std::string()); - identity_anonymous_textfield_->SetText( - UTF8ToUTF16(eap_anonymous_identity)); - } + if (wifi) { + NetworkHandler::Get()->network_configuration_handler()->GetProperties( + service_path_, + base::Bind(&WifiConfigView::InitFromProperties, + weak_ptr_factory_.GetWeakPtr(), show_8021x), + base::Bind(&ShillError, "GetProperties")); + } +} + +void WifiConfigView::InitFromProperties( + bool show_8021x, + const std::string& service_path, + const base::DictionaryValue& properties) { + std::string passphrase; + properties.GetStringWithoutPathExpansion( + flimflam::kPassphraseProperty, &passphrase); + passphrase_textfield_->SetText(UTF8ToUTF16(passphrase)); + + if (!show_8021x) + return; + + // EAP Method + std::string eap_method; + properties.GetStringWithoutPathExpansion( + flimflam::kEapMethodProperty, &eap_method); + if (eap_method == flimflam::kEapMethodPEAP) + eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_PEAP); + else if (eap_method == flimflam::kEapMethodTTLS) + eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TTLS); + else if (eap_method == flimflam::kEapMethodTLS) + eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TLS); + else if (eap_method == flimflam::kEapMethodLEAP) + eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_LEAP); + RefreshEapFields(); + + // Phase 2 authentication and anonymous identity. + if (Phase2AuthActive()) { + std::string eap_phase_2_auth; + properties.GetStringWithoutPathExpansion( + flimflam::kEapPhase2AuthProperty, &eap_phase_2_auth); + if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSMD5) + phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MD5); + else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSMSCHAPV2) + phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAPV2); + else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSMSCHAP) + phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAP); + else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSPAP) + phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_PAP); + else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSCHAP) + phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_CHAP); + + std::string eap_anonymous_identity; + properties.GetStringWithoutPathExpansion( + flimflam::kEapAnonymousIdentityProperty, &eap_anonymous_identity); + identity_anonymous_textfield_->SetText(UTF8ToUTF16(eap_anonymous_identity)); + } - // Server CA certificate. - if (CaCertActive()) { - const std::string& ca_cert_pem = - (wifi ? wifi->eap_server_ca_cert_pem() : std::string()); - if (ca_cert_pem.empty()) { - if (wifi->eap_use_system_cas()) { - // "Default". - server_ca_cert_combobox_->SetSelectedIndex(0); - } else { - // "Do not check". - server_ca_cert_combobox_->SetSelectedIndex( - server_ca_cert_combobox_->model()->GetItemCount() - 1); - } + // Server CA certificate. + if (CaCertActive()) { + std::string eap_ca_cert_pem; + const base::ListValue* pems = NULL; + if (properties.GetListWithoutPathExpansion( + shill::kEapCaCertPemProperty, &pems)) + pems->GetString(0, &eap_ca_cert_pem); + if (eap_ca_cert_pem.empty()) { + bool eap_use_system_cas = false; + properties.GetBooleanWithoutPathExpansion( + flimflam::kEapUseSystemCasProperty, &eap_use_system_cas); + if (eap_use_system_cas) { + // "Default" + server_ca_cert_combobox_->SetSelectedIndex(0); } else { - // Select the certificate if available. - int cert_index = CertLibrary::Get()->GetCertIndexByPEM( - CertLibrary::CERT_TYPE_SERVER_CA, ca_cert_pem); - if (cert_index >= 0) { - // Skip item for "Default". - server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index); - } + // "Do not check". + server_ca_cert_combobox_->SetSelectedIndex( + server_ca_cert_combobox_->model()->GetItemCount() - 1); } - } - - // User certificate. - if (UserCertActive()) { - const std::string& pkcs11_id = - (wifi ? wifi->eap_client_cert_pkcs11_id() : std::string()); - if (!pkcs11_id.empty()) { - int cert_index = CertLibrary::Get()->GetCertIndexByPkcs11Id( - CertLibrary::CERT_TYPE_USER, pkcs11_id); - if (cert_index >= 0) { - user_cert_combobox_->SetSelectedIndex(cert_index); - } + } else { + // Select the certificate if available. + int cert_index = CertLibrary::Get()->GetCertIndexByPEM( + CertLibrary::CERT_TYPE_SERVER_CA, eap_ca_cert_pem); + if (cert_index >= 0) { + // Skip item for "Default". + server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index); } } + } - // Identity is always active. - const std::string& eap_identity = - (wifi ? wifi->eap_identity() : std::string()); - identity_textfield_->SetText(UTF8ToUTF16(eap_identity)); - - // Passphrase - if (PassphraseActive()) { - const std::string& eap_passphrase = - (wifi ? wifi->eap_passphrase() : std::string()); - passphrase_textfield_->SetText(UTF8ToUTF16(eap_passphrase)); + // User certificate. + if (UserCertActive()) { + std::string eap_cert_id; + properties.GetStringWithoutPathExpansion( + flimflam::kEapCertIdProperty, &eap_cert_id); + if (!eap_cert_id.empty()) { + int cert_index = CertLibrary::Get()->GetCertIndexByPkcs11Id( + CertLibrary::CERT_TYPE_USER, eap_cert_id); + if (cert_index >= 0) + user_cert_combobox_->SetSelectedIndex(cert_index); } + } - // Save credentials - bool save_credentials = (wifi ? wifi->save_credentials() : false); - save_credentials_checkbox_->SetChecked(save_credentials); + // Identity is always active. + std::string eap_identity; + properties.GetStringWithoutPathExpansion( + flimflam::kEapIdentityProperty, &eap_identity); + identity_textfield_->SetText(UTF8ToUTF16(eap_identity)); + + // Passphrase + if (PassphraseActive()) { + std::string eap_password; + properties.GetStringWithoutPathExpansion( + flimflam::kEapPasswordProperty, &eap_password); + passphrase_textfield_->SetText(UTF8ToUTF16(eap_password)); } + // Save credentials + bool save_credentials = false; + properties.GetBooleanWithoutPathExpansion( + flimflam::kSaveCredentialsProperty, &save_credentials); + save_credentials_checkbox_->SetChecked(save_credentials); + RefreshShareCheckbox(); UpdateErrorLabel(); } @@ -1244,11 +1250,11 @@ void WifiConfigView::InitFocus() { // static void WifiConfigView::ParseWiFiUIProperty( NetworkPropertyUIData* property_ui_data, - Network* network, + const NetworkState* network, const std::string& key) { onc::ONCSource onc_source = onc::ONC_SOURCE_NONE; const base::DictionaryValue* onc = - NetworkConfigView::FindPolicyForActiveUser(network, &onc_source); + network_connect::FindPolicyForActiveUser(network, &onc_source); property_ui_data->ParseOncProperty( onc_source, @@ -1259,7 +1265,7 @@ void WifiConfigView::ParseWiFiUIProperty( // static void WifiConfigView::ParseWiFiEAPUIProperty( NetworkPropertyUIData* property_ui_data, - Network* network, + const NetworkState* network, const std::string& key) { ParseWiFiUIProperty( property_ui_data, network, diff --git a/chrome/browser/chromeos/options/wifi_config_view.h b/chrome/browser/chromeos/options/wifi_config_view.h index 574072d..573cad6 100644 --- a/chrome/browser/chromeos/options/wifi_config_view.h +++ b/chrome/browser/chromeos/options/wifi_config_view.h @@ -10,10 +10,12 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" #include "base/strings/string16.h" #include "chrome/browser/chromeos/cros/cert_library.h" #include "chrome/browser/chromeos/cros/network_property_ui_data.h" #include "chrome/browser/chromeos/options/network_config_view.h" +#include "third_party/cros_system_api/dbus/service_constants.h" #include "ui/base/models/combobox_model.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/combobox/combobox_listener.h" @@ -28,6 +30,8 @@ class ToggleImageButton; namespace chromeos { +class NetworkState; + namespace internal { class EAPMethodComboboxModel; class Phase2AuthComboboxModel; @@ -43,11 +47,9 @@ class WifiConfigView : public ChildNetworkConfigView, public views::ComboboxListener, public CertLibrary::Observer { public: - // Wifi login dialog for wifi network |wifi|. |wifi| must be a non NULL - // pointer to a WifiNetwork in NetworkLibrary. - WifiConfigView(NetworkConfigView* parent, WifiNetwork* wifi); - // Wifi login dialog for "Joining other network..." - WifiConfigView(NetworkConfigView* parent, bool show_8021x); + WifiConfigView(NetworkConfigView* parent, + const std::string& service_path, + bool show_8021x); virtual ~WifiConfigView(); // views::TextfieldController: @@ -77,18 +79,23 @@ class WifiConfigView : public ChildNetworkConfigView, // Parses a WiFi UI |property| from the ONC associated with |network|. |key| // is the property name within the ONC WiFi dictionary. static void ParseWiFiUIProperty(NetworkPropertyUIData* property_ui_data, - Network* network, + const NetworkState* network, const std::string& key); // Parses a WiFi EAP UI |property| from the ONC associated with |network|. // |key| is the property name within the ONC WiFi.EAP dictionary. static void ParseWiFiEAPUIProperty(NetworkPropertyUIData* property_ui_data, - Network* network, + const NetworkState* network, const std::string& key); private: // Initializes UI. If |show_8021x| includes 802.1x config options. - void Init(WifiNetwork* wifi, bool show_8021x); + void Init(bool show_8021x); + + // Callback to initialize fields from uncached network properties. + void InitFromProperties(bool show_8021x, + const std::string& service_path, + const base::DictionaryValue& dictionary); // Get input values. std::string GetSsid() const; @@ -97,14 +104,17 @@ class WifiConfigView : public ChildNetworkConfigView, bool GetShareNetwork(bool share_default) const; // Get various 802.1X EAP values from the widgets. - EAPMethod GetEapMethod() const; - EAPPhase2Auth GetEapPhase2Auth() const; + std::string GetEapMethod() const; + std::string GetEapPhase2Auth() const; std::string GetEapServerCaCertPEM() const; bool GetEapUseSystemCas() const; std::string GetEapClientCertPkcs11Id() const; std::string GetEapIdentity() const; std::string GetEapAnonymousIdentity() const; + // Fill in |properties| with the appropriate values. + void SetEapProperties(base::DictionaryValue* properties); + // Returns true if the EAP method requires a user certificate. bool UserCertRequired() const; @@ -174,6 +184,8 @@ class WifiConfigView : public ChildNetworkConfigView, views::ToggleImageButton* passphrase_visible_button_; views::Label* error_label_; + base::WeakPtrFactory<WifiConfigView> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(WifiConfigView); }; diff --git a/chrome/browser/chromeos/options/wimax_config_view.cc b/chrome/browser/chromeos/options/wimax_config_view.cc index 5ae075b..8ea3788 100644 --- a/chrome/browser/chromeos/options/wimax_config_view.cc +++ b/chrome/browser/chromeos/options/wimax_config_view.cc @@ -4,19 +4,27 @@ #include "chrome/browser/chromeos/options/wimax_config_view.h" +#include "ash/system/chromeos/network/network_connect.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/chromeos/cros/network_library.h" #include "chrome/browser/chromeos/enrollment_dialog_view.h" #include "chrome/browser/chromeos/login/startup_utils.h" +#include "chrome/browser/chromeos/options/network_connect.h" #include "chrome/browser/profiles/profile_manager.h" #include "chromeos/login/login_state.h" +#include "chromeos/network/network_configuration_handler.h" +#include "chromeos/network/network_event_log.h" +#include "chromeos/network/network_profile.h" +#include "chromeos/network/network_profile_handler.h" +#include "chromeos/network/network_state.h" +#include "chromeos/network/network_state_handler.h" #include "chromeos/network/onc/onc_constants.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "grit/theme_resources.h" +#include "third_party/cros_system_api/dbus/service_constants.h" #include "ui/base/events/event.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -31,8 +39,19 @@ namespace chromeos { -WimaxConfigView::WimaxConfigView(NetworkConfigView* parent, WimaxNetwork* wimax) - : ChildNetworkConfigView(parent, wimax), +namespace { + +void ShillError(const std::string& function, + const std::string& error_name, + scoped_ptr<base::DictionaryValue> error_data) { + NET_LOG_ERROR("Shill Error from WimaxConfigView: " + error_name, function); +} + +} // namespace + +WimaxConfigView::WimaxConfigView(NetworkConfigView* parent, + const std::string& service_path) + : ChildNetworkConfigView(parent, service_path), identity_label_(NULL), identity_textfield_(NULL), save_credentials_checkbox_(NULL), @@ -41,8 +60,9 @@ WimaxConfigView::WimaxConfigView(NetworkConfigView* parent, WimaxNetwork* wimax) passphrase_label_(NULL), passphrase_textfield_(NULL), passphrase_visible_button_(NULL), - error_label_(NULL) { - Init(wimax); + error_label_(NULL), + weak_ptr_factory_(this) { + Init(); } WimaxConfigView::~WimaxConfigView() { @@ -76,33 +96,15 @@ void WimaxConfigView::UpdateDialogButtons() { } void WimaxConfigView::UpdateErrorLabel() { - std::string error_msg; + base::string16 error_msg; if (!service_path_.empty()) { - NetworkLibrary* cros = NetworkLibrary::Get(); - const WimaxNetwork* wimax = cros->FindWimaxNetworkByPath(service_path_); - if (wimax && wimax->failed()) { - bool passphrase_empty = wimax->eap_passphrase().empty(); - switch (wimax->error()) { - case ERROR_BAD_PASSPHRASE: - if (!passphrase_empty) { - error_msg = l10n_util::GetStringUTF8( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE); - } - break; - case ERROR_BAD_WEPKEY: - if (!passphrase_empty) { - error_msg = l10n_util::GetStringUTF8( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_WEPKEY); - } - break; - default: - error_msg = wimax->GetErrorString(); - break; - } - } + const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()-> + GetNetworkState(service_path_); + if (wimax && wimax->connection_state() == flimflam::kStateFailure) + error_msg = ash::network_connect::ErrorString(wimax->error()); } if (!error_msg.empty()) { - error_label_->SetText(UTF8ToUTF16(error_msg)); + error_label_->SetText(error_msg); error_label_->SetVisible(true); } else { error_label_->SetVisible(false); @@ -137,26 +139,26 @@ void WimaxConfigView::ButtonPressed(views::Button* sender, } bool WimaxConfigView::Login() { - NetworkLibrary* cros = NetworkLibrary::Get(); - WimaxNetwork* wimax = cros->FindWimaxNetworkByPath(service_path_); + const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()-> + GetNetworkState(service_path_); if (!wimax) { - // Shill no longer knows about this wimax network (edge case). - // TODO(stevenjb): Add a notification (chromium-os13225). - LOG(WARNING) << "Wimax network: " << service_path_ << " no longer exists."; - return true; + // Shill no longer knows about this network (edge case). + // TODO(stevenjb): Add notification for this. + NET_LOG_ERROR("Network not found", service_path_); + return true; // Close dialog } - wimax->SetEAPIdentity(GetEapIdentity()); - wimax->SetEAPPassphrase(GetEapPassphrase()); - wimax->SetSaveCredentials(GetSaveCredentials()); - bool share_default = (wimax->profile_type() != PROFILE_USER); - bool share = GetShareNetwork(share_default); - wimax->SetEnrollmentDelegate( - CreateEnrollmentDelegate(GetWidget()->GetNativeWindow(), - wimax->name(), - ProfileManager::GetLastUsedProfile())); - cros->ConnectToWimaxNetwork(wimax, share); - // Connection failures are responsible for updating the UI, including - // reopening dialogs. + base::DictionaryValue properties; + properties.SetStringWithoutPathExpansion( + flimflam::kEapIdentityProperty, GetEapIdentity()); + properties.SetStringWithoutPathExpansion( + flimflam::kEapPasswordProperty, GetEapPassphrase()); + properties.SetBooleanWithoutPathExpansion( + flimflam::kSaveCredentialsProperty, GetSaveCredentials()); + + const bool share_default = true; + bool share_network = GetShareNetwork(share_default); + ash::network_connect::ConfigureNetworkAndConnect( + service_path_, properties, share_network); return true; // dialog will be closed } @@ -183,8 +185,11 @@ bool WimaxConfigView::GetShareNetwork(bool share_default) const { void WimaxConfigView::Cancel() { } -void WimaxConfigView::Init(WimaxNetwork* wimax) { - DCHECK(wimax); +void WimaxConfigView::Init() { + const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()-> + GetNetworkState(service_path_); + DCHECK(wimax && wimax->type() == flimflam::kTypeWimax); + WifiConfigView::ParseWiFiEAPUIProperty( &save_credentials_ui_data_, wimax, onc::eap::kSaveCredentials); WifiConfigView::ParseWiFiEAPUIProperty( @@ -230,8 +235,6 @@ void WimaxConfigView::Init(WimaxNetwork* wimax) { views::Textfield::STYLE_DEFAULT); identity_textfield_->SetAccessibleName(identity_label_text); identity_textfield_->SetController(this); - const std::string& eap_identity = wimax->eap_identity(); - identity_textfield_->SetText(UTF8ToUTF16(eap_identity)); identity_textfield_->SetEnabled(identity_ui_data_.IsEditable()); layout->AddView(identity_textfield_); layout->AddView(new ControlledSettingIndicatorView(identity_ui_data_)); @@ -288,7 +291,7 @@ void WimaxConfigView::Init(WimaxNetwork* wimax) { // Checkboxes. - if (LoginState::Get()->IsUserLoggedIn()) { + if (LoginState::Get()->IsUserAuthenticated()) { // Save credentials layout->StartRow(0, column_view_set_id); save_credentials_checkbox_ = new views::Checkbox( @@ -296,23 +299,28 @@ void WimaxConfigView::Init(WimaxNetwork* wimax) { IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS)); save_credentials_checkbox_->SetEnabled( save_credentials_ui_data_.IsEditable()); - save_credentials_checkbox_->SetChecked(wimax->save_credentials()); layout->SkipColumns(1); layout->AddView(save_credentials_checkbox_); layout->AddView( new ControlledSettingIndicatorView(save_credentials_ui_data_)); + } - // Share network - if (wimax->profile_type() == PROFILE_NONE && wimax->passphrase_required()) { - layout->StartRow(0, column_view_set_id); - share_network_checkbox_ = new views::Checkbox( - l10n_util::GetStringUTF16( - IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SHARE_NETWORK)); + // Share network + if (wimax->profile_path().empty()) { + layout->StartRow(0, column_view_set_id); + share_network_checkbox_ = new views::Checkbox( + l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SHARE_NETWORK)); + if (LoginState::Get()->IsUserAuthenticated()) { + share_network_checkbox_->SetChecked(false); // Default to unshared share_network_checkbox_->SetEnabled(true); - share_network_checkbox_->SetChecked(false); // Default to unshared. - layout->SkipColumns(1); - layout->AddView(share_network_checkbox_); + } else { + // Not logged in, must be shared + share_network_checkbox_->SetChecked(true); + share_network_checkbox_->SetEnabled(false); } + layout->SkipColumns(1); + layout->AddView(share_network_checkbox_); } layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); @@ -325,6 +333,32 @@ void WimaxConfigView::Init(WimaxNetwork* wimax) { layout->AddView(error_label_); UpdateErrorLabel(); + + if (wimax) { + NetworkHandler::Get()->network_configuration_handler()->GetProperties( + service_path_, + base::Bind(&WimaxConfigView::InitFromProperties, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&ShillError, "GetProperties")); + } +} + +void WimaxConfigView::InitFromProperties( + const std::string& service_path, + const base::DictionaryValue& properties) { + // EapIdentity + std::string eap_identity; + properties.GetStringWithoutPathExpansion( + flimflam::kEapIdentityProperty, &eap_identity); + identity_textfield_->SetText(UTF8ToUTF16(eap_identity)); + + // Save credentials + if (save_credentials_checkbox_) { + bool save_credentials = false; + properties.GetBooleanWithoutPathExpansion( + flimflam::kSaveCredentialsProperty, &save_credentials); + save_credentials_checkbox_->SetChecked(save_credentials); + } } void WimaxConfigView::InitFocus() { diff --git a/chrome/browser/chromeos/options/wimax_config_view.h b/chrome/browser/chromeos/options/wimax_config_view.h index f76702a..baa3ae7 100644 --- a/chrome/browser/chromeos/options/wimax_config_view.h +++ b/chrome/browser/chromeos/options/wimax_config_view.h @@ -9,6 +9,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/memory/weak_ptr.h" #include "base/strings/string16.h" #include "chrome/browser/chromeos/options/network_config_view.h" #include "chrome/browser/chromeos/options/wifi_config_view.h" @@ -31,7 +32,7 @@ class WimaxConfigView : public ChildNetworkConfigView, public: // Wimax login dialog for wimax network |wimax|. |wimax| must be a non NULL // pointer to a WimaxNetwork in NetworkLibrary. - WimaxConfigView(NetworkConfigView* parent, WimaxNetwork* wimax); + WimaxConfigView(NetworkConfigView* parent, const std::string& service_path); virtual ~WimaxConfigView(); // views::TextfieldController: @@ -53,7 +54,12 @@ class WimaxConfigView : public ChildNetworkConfigView, virtual void InitFocus() OVERRIDE; private: - void Init(WimaxNetwork* wimax); + // Initializes UI. + void Init(); + + // Callback to initialize fields from uncached network properties. + void InitFromProperties(const std::string& service_path, + const base::DictionaryValue& dictionary); // Get input values. std::string GetEapIdentity() const; @@ -81,6 +87,8 @@ class WimaxConfigView : public ChildNetworkConfigView, views::ToggleImageButton* passphrase_visible_button_; views::Label* error_label_; + base::WeakPtrFactory<WimaxConfigView> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(WimaxConfigView); }; diff --git a/chrome/browser/chromeos/status/network_menu.cc b/chrome/browser/chromeos/status/network_menu.cc index 980af04..2701f92 100644 --- a/chrome/browser/chromeos/status/network_menu.cc +++ b/chrome/browser/chromeos/status/network_menu.cc @@ -8,6 +8,7 @@ #include "ash/shell.h" #include "ash/shell_delegate.h" +#include "ash/system/chromeos/network/network_connect.h" #include "ash/system/chromeos/network/network_icon.h" #include "base/bind.h" #include "base/logging.h" @@ -17,7 +18,6 @@ #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/mobile_config.h" #include "chrome/browser/chromeos/options/network_config_view.h" -#include "chrome/browser/chromeos/options/network_connect.h" #include "chrome/browser/defaults.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/url_constants.h" @@ -219,17 +219,9 @@ class MainMenuModel : public NetworkMenuModel { void NetworkMenuModel::ConnectToNetworkAt(int index) { const std::string& service_path = menu_items_[index].service_path; - network_connect::ConnectResult result = - network_connect::ConnectToNetwork( - service_path, owner_->delegate()->GetNativeWindow()); + gfx::NativeWindow native_window = owner_->delegate()->GetNativeWindow(); + ash::network_connect::ConnectToNetwork(service_path, native_window); owner_->delegate()->OnConnectToNetworkRequested(service_path); - if (result == network_connect::NETWORK_NOT_FOUND) { - // If we are attempting to connect to a network that no longer exists, - // display a notification. - LOG(WARNING) << "Network does not exist to connect to: " - << service_path; - // TODO(stevenjb): Show notification. - } } //////////////////////////////////////////////////////////////////////////////// @@ -350,7 +342,7 @@ void NetworkMenuModel::ShowOther(const std::string& type) const { if (type == flimflam::kTypeCellular) ChooseMobileNetworkDialog::ShowDialog(native_window); else - NetworkConfigView::ShowForType(chromeos::TYPE_WIFI, native_window); + NetworkConfigView::ShowForType(flimflam::kTypeWifi, native_window); } //////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc index 7a8a0fa..1810a55e 100644 --- a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc +++ b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc @@ -490,24 +490,7 @@ class SystemTrayDelegate : public ash::SystemTrayDelegate, virtual void ShowNetworkSettings(const std::string& service_path) OVERRIDE { if (!LoginState::Get()->IsUserLoggedIn()) return; - - std::string page = chrome::kInternetOptionsSubPage; - const chromeos::NetworkState* network = service_path.empty() ? NULL : - NetworkHandler::Get()->network_state_handler()->GetNetworkState( - service_path); - if (network) { - std::string name(network->name()); - if (name.empty() && network->type() == flimflam::kTypeEthernet) - name = l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET); - page += base::StringPrintf( - "?servicePath=%s&networkType=%s&networkName=%s", - net::EscapeUrlEncodedData(service_path, true).c_str(), - net::EscapeUrlEncodedData(network->type(), true).c_str(), - net::EscapeUrlEncodedData(name, false).c_str()); - } - content::RecordAction( - content::UserMetricsAction("OpenInternetOptionsDialog")); - chrome::ShowSettingsSubPage(GetAppropriateBrowser(), page); + network_connect::ShowNetworkSettings(service_path); } virtual void ShowBluetoothSettings() OVERRIDE { @@ -768,15 +751,12 @@ class SystemTrayDelegate : public ash::SystemTrayDelegate, network_connect::HandleUnconfiguredNetwork(network_id, GetNativeWindow()); } - virtual void ConnectToNetwork(const std::string& network_id) OVERRIDE { - DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch( - chromeos::switches::kUseNewNetworkConnectionHandler)); - network_connect::ConnectResult result = - network_connect::ConnectToNetwork(network_id, GetNativeWindow()); - if (result == network_connect::NETWORK_NOT_FOUND) - ShowNetworkSettings(""); - else if (result == network_connect::CONNECT_NOT_STARTED) - ShowNetworkSettings(network_id); + virtual void EnrollOrConfigureNetwork( + const std::string& network_id, + gfx::NativeWindow parent_window) OVERRIDE { + if (network_connect::EnrollNetwork(network_id, parent_window)) + return; + network_connect::HandleUnconfiguredNetwork(network_id, parent_window); } virtual void ManageBluetoothDevices() OVERRIDE { @@ -798,12 +778,16 @@ class SystemTrayDelegate : public ash::SystemTrayDelegate, SimDialogDelegate::SIM_DIALOG_UNLOCK); } + virtual void ShowMobileSetup(const std::string& network_id) OVERRIDE { + network_connect::ShowMobileSetup(network_id); + } + virtual void ShowOtherWifi() OVERRIDE { - NetworkConfigView::ShowForType(chromeos::TYPE_WIFI, GetNativeWindow()); + NetworkConfigView::ShowForType(flimflam::kTypeWifi, GetNativeWindow()); } virtual void ShowOtherVPN() OVERRIDE { - NetworkConfigView::ShowForType(chromeos::TYPE_VPN, GetNativeWindow()); + NetworkConfigView::ShowForType(flimflam::kTypeVPN, GetNativeWindow()); } virtual void ShowOtherCellular() OVERRIDE { @@ -1253,10 +1237,12 @@ class SystemTrayDelegate : public ash::SystemTrayDelegate, ash::NetworkObserver::MessageType message_type, size_t link_index) OVERRIDE { if (message_type == ash::NetworkObserver::ERROR_OUT_OF_CREDITS) { - const CellularNetwork* cellular = - NetworkLibrary::Get()->cellular_network(); - if (cellular) - ConnectToNetwork(cellular->service_path()); + const NetworkState* cellular = + NetworkHandler::Get()->network_state_handler()-> + FirstNetworkByType(flimflam::kTypeCellular); + std::string service_path = cellular ? cellular->path() : ""; + ShowNetworkSettings(service_path); + ash::Shell::GetInstance()->system_tray_notifier()-> NotifyClearNetworkMessage(message_type); } diff --git a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc index 6873b01d..6537a55 100644 --- a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc @@ -281,15 +281,6 @@ void SetNetworkProperty(const std::string& service_path, base::Bind(&ShillError, "SetNetworkProperty")); } -const base::DictionaryValue* FindPolicyForActiveUser( - const NetworkState* network, - onc::ONCSource* onc_source) { - const User* user = UserManager::Get()->GetActiveUser(); - std::string username_hash = user ? user->username_hash() : std::string(); - return NetworkHandler::Get()->managed_network_configuration_handler() - ->FindPolicyByGUID(username_hash, network->guid(), onc_source); -} - std::string ActivationStateString(const std::string& activation_state) { int id; if (activation_state == flimflam::kActivationStateActivated) @@ -656,7 +647,8 @@ void PopulateVPNDetails(const NetworkState* vpn, dictionary->SetString(kTagUsername, username); onc::ONCSource onc_source = onc::ONC_SOURCE_NONE; - const base::DictionaryValue* onc = FindPolicyForActiveUser(vpn, &onc_source); + const base::DictionaryValue* onc = + network_connect::FindPolicyForActiveUser(vpn, &onc_source); NetworkPropertyUIData hostname_ui_data; hostname_ui_data.ParseOncProperty( @@ -1165,7 +1157,7 @@ void InternetOptionsHandler::CarrierStatusCallback() { const NetworkState* network = handler->FirstNetworkByType(flimflam::kTypeCellular); if (network) { - chromeos::network_connect::ActivateCellular(network->path()); + ash::network_connect::ActivateCellular(network->path()); UpdateConnectionData(network->path()); } } @@ -1447,7 +1439,7 @@ void InternetOptionsHandler::PopulateDictionaryDetailsCallback( onc::ONCSource onc_source = onc::ONC_SOURCE_NONE; const base::DictionaryValue* onc = - FindPolicyForActiveUser(network, &onc_source); + network_connect::FindPolicyForActiveUser(network, &onc_source); const NetworkPropertyUIData property_ui_data(onc_source); base::DictionaryValue dictionary; @@ -1692,7 +1684,7 @@ void PopulateCellularDetails(const NetworkState* cellular, // caching them (will be done for the new UI). const base::DictionaryValue& device_properties = device->properties(); const NetworkPropertyUIData cellular_property_ui_data( - cellular->onc_source()); + cellular->ui_data().onc_source()); CopyStringFromDictionary(device_properties, flimflam::kManufacturerProperty, kTagManufacturer, dictionary); CopyStringFromDictionary(device_properties, flimflam::kModelIDProperty, @@ -1850,17 +1842,16 @@ void InternetOptionsHandler::NetworkCommandCallback( weak_factory_.GetWeakPtr()), base::Bind(&ShillError, "NetworkCommand: " + command)); } else if (command == kTagConnect) { - network_connect::ConnectToNetwork( - service_path, GetNativeWindow()); + ash::network_connect::ConnectToNetwork(service_path, GetNativeWindow()); } else if (command == kTagDisconnect) { NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork( service_path, base::Bind(&base::DoNothing), base::Bind(&ShillError, "NetworkCommand: " + command)); } else if (command == kTagConfigure) { - NetworkConfigView::ShowForPath(service_path, GetNativeWindow()); + NetworkConfigView::Show(service_path, GetNativeWindow()); } else if (command == kTagActivate && type == flimflam::kTypeCellular) { - network_connect::ActivateCellular(service_path); + ash::network_connect::ActivateCellular(service_path); // Activation may update network properties (e.g. ActivationState), so // request them here in case they change. UpdateConnectionData(service_path); @@ -1872,9 +1863,9 @@ void InternetOptionsHandler::NetworkCommandCallback( void InternetOptionsHandler::AddConnection(const std::string& type) { if (type == flimflam::kTypeWifi) - NetworkConfigView::ShowForType(chromeos::TYPE_WIFI, GetNativeWindow()); + NetworkConfigView::ShowForType(flimflam::kTypeWifi, GetNativeWindow()); else if (type == flimflam::kTypeVPN) - NetworkConfigView::ShowForType(chromeos::TYPE_VPN, GetNativeWindow()); + NetworkConfigView::ShowForType(flimflam::kTypeVPN, GetNativeWindow()); else if (type == flimflam::kTypeCellular) ChooseMobileNetworkDialog::ShowDialog(GetNativeWindow()); else diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc index 26c3752..4b88a5f 100644 --- a/chromeos/chromeos_switches.cc +++ b/chromeos/chromeos_switches.cc @@ -192,8 +192,5 @@ const char kStubCrosSettings[] = "stub-cros-settings"; const char kUseNewNetworkConfigurationHandlers[] = "use-new-network-configuration-handlers"; -const char kUseNewNetworkConnectionHandler[] = - "use-new-network-connection-handler"; - } // namespace switches } // namespace chromeos diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h index 76a66bc..794a5fb 100644 --- a/chromeos/chromeos_switches.h +++ b/chromeos/chromeos_switches.h @@ -71,7 +71,6 @@ CHROMEOS_EXPORT extern const char kSkipHWIDCheck[]; CHROMEOS_EXPORT extern const char kSmsTestMessages[]; CHROMEOS_EXPORT extern const char kStubCrosSettings[]; CHROMEOS_EXPORT extern const char kUseNewNetworkConfigurationHandlers[]; -CHROMEOS_EXPORT extern const char kUseNewNetworkConnectionHandler[]; } // namespace switches } // namespace chromeos diff --git a/chromeos/network/favorite_state.cc b/chromeos/network/favorite_state.cc index 90043e9..2bc6b8e 100644 --- a/chromeos/network/favorite_state.cc +++ b/chromeos/network/favorite_state.cc @@ -15,32 +15,31 @@ namespace chromeos { FavoriteState::FavoriteState(const std::string& path) - : ManagedState(MANAGED_TYPE_FAVORITE, path), - onc_source_(onc::ONC_SOURCE_NONE) { + : ManagedState(MANAGED_TYPE_FAVORITE, path) { } FavoriteState::~FavoriteState() { } bool FavoriteState::PropertyChanged(const std::string& key, - const base::Value& value) { + const base::Value& value) { if (ManagedStatePropertyChanged(key, value)) return true; if (key == flimflam::kProfileProperty) { return GetStringValue(key, value, &profile_path_); } else if (key == flimflam::kUIDataProperty) { - if (!NetworkState::GetOncSource(value, &onc_source_)) { + if (!NetworkState::GetUIDataFromValue(value, &ui_data_)) { NET_LOG_ERROR("Failed to parse " + key, path()); return false; } return true; -} + } return false; } bool FavoriteState::IsManaged() const { - return onc_source_ == onc::ONC_SOURCE_DEVICE_POLICY || - onc_source_ == onc::ONC_SOURCE_USER_POLICY; + return ui_data_.onc_source() == onc::ONC_SOURCE_DEVICE_POLICY || + ui_data_.onc_source() == onc::ONC_SOURCE_USER_POLICY; } bool FavoriteState::IsPrivate() const { diff --git a/chromeos/network/favorite_state.h b/chromeos/network/favorite_state.h index 4fa03f3..53f9281 100644 --- a/chromeos/network/favorite_state.h +++ b/chromeos/network/favorite_state.h @@ -6,6 +6,7 @@ #define CHROMEOS_NETWORK_FAVORITE_STATE_H_ #include "chromeos/network/managed_state.h" +#include "chromeos/network/network_ui_data.h" #include "chromeos/network/onc/onc_constants.h" namespace chromeos { @@ -30,7 +31,7 @@ class CHROMEOS_EXPORT FavoriteState : public ManagedState { // Accessors const std::string& profile_path() const { return profile_path_; } bool is_favorite() const { return !profile_path_.empty(); } - onc::ONCSource onc_source() const { return onc_source_; } + const NetworkUIData& ui_data() const { return ui_data_; } // Returns true if the ONC source is a device or user policy. bool IsManaged() const; @@ -40,7 +41,7 @@ class CHROMEOS_EXPORT FavoriteState : public ManagedState { private: std::string profile_path_; - onc::ONCSource onc_source_; + NetworkUIData ui_data_; DISALLOW_COPY_AND_ASSIGN(FavoriteState); }; diff --git a/chromeos/network/network_configuration_handler.cc b/chromeos/network/network_configuration_handler.cc index f7f118e..fbd73c6 100644 --- a/chromeos/network/network_configuration_handler.cc +++ b/chromeos/network/network_configuration_handler.cc @@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/format_macros.h" +#include "base/json/json_writer.h" #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" @@ -66,6 +67,43 @@ void GetPropertiesCallback( *properties_copy.get()); } +void SetNetworkProfileErrorCallback( + const std::string& service_path, + const std::string& profile_path, + const network_handler::ErrorCallback& error_callback, + const std::string& dbus_error_name, + const std::string& dbus_error_message) { + network_handler::ShillErrorCallbackFunction( + "Config.SetNetworkProfile Failed: " + profile_path, + service_path, error_callback, + dbus_error_name, dbus_error_message); +} + +bool IsPassphrase(const std::string& key) { + return key == flimflam::kEapPrivateKeyPasswordProperty || + key == flimflam::kEapPasswordProperty || + key == flimflam::kL2tpIpsecPasswordProperty || + key == flimflam::kOpenVPNPasswordProperty || + key == flimflam::kPassphraseProperty || + key == flimflam::kOpenVPNOTPProperty || + key == flimflam::kEapPrivateKeyProperty || + key == flimflam::kEapPrivateKeyPasswordProperty || + key == flimflam::kEapPinProperty || + key == flimflam::kApnPasswordProperty; +} + +void LogConfigProperties(const std::string& desc, + const std::string& path, + const base::DictionaryValue& properties) { + for (base::DictionaryValue::Iterator iter(properties); + !iter.IsAtEnd(); iter.Advance()) { + std::string v = "******"; + if (!IsPassphrase(iter.key())) + base::JSONWriter::Write(&iter.value(), &v); + NET_LOG_DEBUG(desc, path + "." + iter.key() + "=" + v); + } +} + } // namespace // Helper class to request from Shill the profile entries associated with a @@ -188,7 +226,14 @@ void NetworkConfigurationHandler::SetProperties( const base::DictionaryValue& properties, const base::Closure& callback, const network_handler::ErrorCallback& error_callback) { + if (properties.empty()) { + if (!callback.is_null()) + callback.Run(); + return; + } NET_LOG_USER("SetProperties", service_path); + LogConfigProperties("SetProperty", service_path, properties); + DBusThreadManager::Get()->GetShillServiceClient()->SetProperties( dbus::ObjectPath(service_path), properties, @@ -203,7 +248,16 @@ void NetworkConfigurationHandler::ClearProperties( const std::vector<std::string>& names, const base::Closure& callback, const network_handler::ErrorCallback& error_callback) { + if (names.empty()) { + if (!callback.is_null()) + callback.Run(); + return; + } NET_LOG_USER("ClearProperties", service_path); + for (std::vector<std::string>::const_iterator iter = names.begin(); + iter != names.end(); ++iter) { + NET_LOG_DEBUG("ClearProperty", service_path + "." + *iter); + } DBusThreadManager::Get()->GetShillServiceClient()->ClearProperties( dbus::ObjectPath(service_path), names, @@ -219,9 +273,12 @@ void NetworkConfigurationHandler::CreateConfiguration( const network_handler::ErrorCallback& error_callback) { ShillManagerClient* manager = DBusThreadManager::Get()->GetShillManagerClient(); - std::string type; properties.GetStringWithoutPathExpansion(flimflam::kTypeProperty, &type); + + NET_LOG_USER("CreateConfiguration", type); + LogConfigProperties("Configure", type, properties); + // Shill supports ConfigureServiceForProfile only for network type WiFi. In // all other cases, we have to rely on GetService for now. This is // unproblematic for VPN (user profile only), but will lead to inconsistencies @@ -265,6 +322,22 @@ void NetworkConfigurationHandler::RemoveConfiguration( deleter->Run(); } +void NetworkConfigurationHandler::SetNetworkProfile( + const std::string& service_path, + const std::string& profile_path, + const base::Closure& callback, + const network_handler::ErrorCallback& error_callback) { + NET_LOG_USER("SetNetworkProfile", service_path + ": " + profile_path); + base::StringValue profile_path_value(profile_path); + DBusThreadManager::Get()->GetShillServiceClient()->SetProperty( + dbus::ObjectPath(service_path), + flimflam::kProfileProperty, + profile_path_value, + callback, + base::Bind(&SetNetworkProfileErrorCallback, + service_path, profile_path, error_callback)); +} + // NetworkConfigurationHandler Private methods NetworkConfigurationHandler::NetworkConfigurationHandler() diff --git a/chromeos/network/network_configuration_handler.h b/chromeos/network/network_configuration_handler.h index 9ef1131..f1ee856 100644 --- a/chromeos/network/network_configuration_handler.h +++ b/chromeos/network/network_configuration_handler.h @@ -99,6 +99,13 @@ class CHROMEOS_EXPORT NetworkConfigurationHandler const base::Closure& callback, const network_handler::ErrorCallback& error_callback); + // Changes the profile for the network |service_path| to |profile_path|. + // See note on |callback| and |error_callback| in class description above. + void SetNetworkProfile(const std::string& service_path, + const std::string& profile_path, + const base::Closure& callback, + const network_handler::ErrorCallback& error_callback); + // Construct and initialize an instance for testing. static NetworkConfigurationHandler* InitializeForTest( NetworkStateHandler* network_state_handler); diff --git a/chromeos/network/network_connection_handler.cc b/chromeos/network/network_connection_handler.cc index 66e8d4f..f7ec893 100644 --- a/chromeos/network/network_connection_handler.cc +++ b/chromeos/network/network_connection_handler.cc @@ -62,56 +62,40 @@ bool NetworkRequiresActivation(const NetworkState* network) { } bool VPNIsConfigured(const std::string& service_path, - const base::DictionaryValue& service_properties) { - // VPN Provider values are read from the "Provider" dictionary, not the - // "Provider.Type", etc keys (which are used only to set the values). - const base::DictionaryValue* provider_properties; - if (!service_properties.GetDictionaryWithoutPathExpansion( - flimflam::kProviderProperty, &provider_properties)) { - NET_LOG_ERROR("VPN Provider Dictionary not present", service_path); - return false; - } - std::string provider_type; - if (!provider_properties->GetStringWithoutPathExpansion( - flimflam::kTypeProperty, &provider_type)) { - NET_LOG_ERROR("VPN Provider Type not present", service_path); - return false; - } + const std::string& provider_type, + const base::DictionaryValue& provider_properties) { if (provider_type == flimflam::kProviderOpenVpn) { std::string hostname; - provider_properties->GetStringWithoutPathExpansion( + provider_properties.GetStringWithoutPathExpansion( flimflam::kHostProperty, &hostname); if (hostname.empty()) { NET_LOG_EVENT("OpenVPN: No hostname", service_path); return false; } std::string username; - provider_properties->GetStringWithoutPathExpansion( + provider_properties.GetStringWithoutPathExpansion( flimflam::kOpenVPNUserProperty, &username); if (username.empty()) { NET_LOG_EVENT("OpenVPN: No username", service_path); return false; } bool passphrase_required = false; - provider_properties->GetBooleanWithoutPathExpansion( + provider_properties.GetBooleanWithoutPathExpansion( flimflam::kPassphraseRequiredProperty, &passphrase_required); - std::string passphrase; - provider_properties->GetStringWithoutPathExpansion( - flimflam::kOpenVPNPasswordProperty, &passphrase); - if (passphrase_required && passphrase.empty()) { - NET_LOG_EVENT("OpenVPN: No passphrase", service_path); + if (passphrase_required) { + NET_LOG_EVENT("OpenVPN: Passphrase Required", service_path); return false; } NET_LOG_EVENT("OpenVPN Is Configured", service_path); } else { bool passphrase_required = false; std::string passphrase; - provider_properties->GetBooleanWithoutPathExpansion( + provider_properties.GetBooleanWithoutPathExpansion( flimflam::kL2tpIpsecPskRequiredProperty, &passphrase_required); - provider_properties->GetStringWithoutPathExpansion( - flimflam::kL2tpIpsecPskProperty, &passphrase); - if (passphrase_required && passphrase.empty()) + if (passphrase_required) { + NET_LOG_EVENT("VPN: Passphrase Required", service_path); return false; + } NET_LOG_EVENT("VPN Is Configured", service_path); } return true; @@ -135,10 +119,8 @@ const char NetworkConnectionHandler::kErrorAuthenticationRequired[] = "authentication-required"; const char NetworkConnectionHandler::kErrorShillError[] = "shill-error"; const char NetworkConnectionHandler::kErrorConnectFailed[] = "connect-failed"; -const char NetworkConnectionHandler::kErrorDisconnectFailed[] = - "disconnect-failed"; -const char NetworkConnectionHandler::kErrorMissingProviderType[] = - "missing-provider-type"; +const char NetworkConnectionHandler::kErrorMissingProvider[] = + "missing-provider"; const char NetworkConnectionHandler::kErrorUnknown[] = "unknown-error"; struct NetworkConnectionHandler::ConnectRequest { @@ -203,10 +185,6 @@ void NetworkConnectionHandler::Init( void NetworkConnectionHandler::LoggedInStateChanged( LoginState::LoggedInState state) { - NET_LOG_EVENT("NewNetworkConnectionHandler", - CommandLine::ForCurrentProcess()->HasSwitch( - chromeos::switches::kUseNewNetworkConnectionHandler) ? - "enabled" : "disabled"); if (state == LoginState::LOGGED_IN_ACTIVE) { logged_in_ = true; NET_LOG_EVENT("Logged In", ""); @@ -316,6 +294,21 @@ void NetworkConnectionHandler::DisconnectNetwork( CallShillDisconnect(service_path, success_callback, error_callback); } +void NetworkConnectionHandler::ActivateNetwork( + const std::string& service_path, + const std::string& carrier, + const base::Closure& success_callback, + const network_handler::ErrorCallback& error_callback) { + NET_LOG_USER("DisconnectNetwork", service_path); + const NetworkState* network = + network_state_handler_->GetNetworkState(service_path); + if (!network) { + InvokeErrorCallback(service_path, error_callback, kErrorNotFound); + return; + } + CallShillActivate(service_path, carrier, success_callback, error_callback); +} + bool NetworkConnectionHandler::HasConnectingNetwork( const std::string& service_path) { return pending_requests_.count(service_path) != 0; @@ -381,14 +374,39 @@ void NetworkConnectionHandler::VerifyConfiguredAndConnect( return; } - // VPN requires a host and username to be set. - if (type == flimflam::kTypeVPN && - !VPNIsConfigured(service_path, service_properties)) { - ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); - return; + // Get VPN provider type and host (required for configuration) and ensure + // that required VPN non-cert properties are set. + std::string vpn_provider_type, vpn_provider_host; + if (type == flimflam::kTypeVPN) { + // VPN Provider values are read from the "Provider" dictionary, not the + // "Provider.Type", etc keys (which are used only to set the values). + const base::DictionaryValue* provider_properties; + if (service_properties.GetDictionaryWithoutPathExpansion( + flimflam::kProviderProperty, &provider_properties)) { + provider_properties->GetStringWithoutPathExpansion( + flimflam::kTypeProperty, &vpn_provider_type); + provider_properties->GetStringWithoutPathExpansion( + flimflam::kHostProperty, &vpn_provider_host); + } + if (vpn_provider_type.empty() || vpn_provider_host.empty()) { + ErrorCallbackForPendingRequest(service_path, kErrorMissingProvider); + return; + } + // VPN requires a host and username to be set. + if (!VPNIsConfigured( + service_path, vpn_provider_type, *provider_properties)) { + NET_LOG_ERROR("VPN Not Configured", service_path); + ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); + return; + } } - // Check certificate properties in kUIDataProperty. + // These will be set if they need to be configured, otherwise they will + // be left empty and the properties will not be set. + std::string pkcs11_id, tpm_slot, tpm_pin; + + // Check certificate properties in kUIDataProperty if configured. + // Note: Wifi/VPNConfigView set these properties explicitly. scoped_ptr<NetworkUIData> ui_data = ManagedNetworkConfigurationHandler::GetUIData(service_properties); if (ui_data && ui_data->certificate_type() == CLIENT_CERT_TYPE_PATTERN) { @@ -397,6 +415,7 @@ void NetworkConnectionHandler::VerifyConfiguredAndConnect( ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired); return; } + // If certificates have not been loaded yet, queue the connect request. if (!certificates_loaded_) { ConnectRequest* request = pending_request(service_path); @@ -408,68 +427,79 @@ void NetworkConnectionHandler::VerifyConfiguredAndConnect( return; } - // Ensure the certificate is available. - std::string pkcs11_id; + // Ensure the certificate is available and configured. if (!CertificateIsConfigured(ui_data.get(), &pkcs11_id)) { ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired); return; } + } - // The network may not be 'Connectable' because the certificate data is - // not set up, so configure tpm slot/pin and pkcs11_id before connecting. - // TODO(stevenjb): Remove this code once NetworkConfigurationHandler - // handles this. - NET_LOG_EVENT("Configuring Network", service_path); - const std::string& tpm_slot = cert_loader_->tpm_token_slot(); - const std::string& tpm_pin = cert_loader_->tpm_user_pin(); - base::DictionaryValue config_properties; - // Set configuration properties required by Shill to identify the network. - config_properties.SetStringWithoutPathExpansion( - flimflam::kTypeProperty, type); - CopyStringFromDictionary(service_properties, flimflam::kNameProperty, - &config_properties); - CopyStringFromDictionary(service_properties, flimflam::kSecurityProperty, - &config_properties); - CopyStringFromDictionary(service_properties, flimflam::kGuidProperty, - &config_properties); + // The network may not be 'Connectable' because the TPM properties are + // not set up, so configure tpm slot/pin before connecting. + if (cert_loader_) { + tpm_slot = cert_loader_->tpm_token_slot(); + tpm_pin = cert_loader_->tpm_user_pin(); + } - if (type == flimflam::kTypeVPN) { - // VPN Provider values are read from the "Provider" dictionary, not the - // "Provider.Type", etc keys (which are used only to set the values). - std::string provider_type; - const base::DictionaryValue* provider_properties; - if (service_properties.GetDictionaryWithoutPathExpansion( - flimflam::kProviderProperty, &provider_properties)) { - provider_properties->GetStringWithoutPathExpansion( - flimflam::kTypeProperty, &provider_type); - } - if (provider_type.empty()) { - ErrorCallbackForPendingRequest(service_path, kErrorMissingProviderType); - return; - } - if (provider_type == flimflam::kProviderOpenVpn) { + base::DictionaryValue config_properties; + + if (type == flimflam::kTypeVPN) { + if (vpn_provider_type == flimflam::kProviderOpenVpn) { + if (!pkcs11_id.empty()) { config_properties.SetStringWithoutPathExpansion( - flimflam::kOpenVPNClientCertSlotProperty, tpm_slot); + flimflam::kOpenVPNClientCertIdProperty, pkcs11_id); + } + if (!tpm_pin.empty()) { config_properties.SetStringWithoutPathExpansion( flimflam::kOpenVPNPinProperty, tpm_pin); + } + } else { + if (!pkcs11_id.empty()) { config_properties.SetStringWithoutPathExpansion( - flimflam::kOpenVPNClientCertIdProperty, pkcs11_id); - } else { + flimflam::kL2tpIpsecClientCertIdProperty, pkcs11_id); + } + if (!tpm_slot.empty()) { config_properties.SetStringWithoutPathExpansion( flimflam::kL2tpIpsecClientCertSlotProperty, tpm_slot); + } + if (!tpm_pin.empty()) { config_properties.SetStringWithoutPathExpansion( flimflam::kL2tpIpsecPinProperty, tpm_pin); - config_properties.SetStringWithoutPathExpansion( - flimflam::kL2tpIpsecClientCertIdProperty, pkcs11_id); } - } else if (type == flimflam::kTypeWifi) { - config_properties.SetStringWithoutPathExpansion( - flimflam::kEapPinProperty, cert_loader_->tpm_user_pin()); + } + } else if (type == flimflam::kTypeWifi) { + if (!pkcs11_id.empty()) { config_properties.SetStringWithoutPathExpansion( flimflam::kEapCertIdProperty, pkcs11_id); config_properties.SetStringWithoutPathExpansion( flimflam::kEapKeyIdProperty, pkcs11_id); } + if (!tpm_pin.empty()) { + config_properties.SetStringWithoutPathExpansion( + flimflam::kEapPinProperty, tpm_pin); + } + } + + if (!config_properties.empty()) { + NET_LOG_EVENT("Configuring Network", service_path); + + // Set configuration properties required by Shill to identify the network. + config_properties.SetStringWithoutPathExpansion( + flimflam::kTypeProperty, type); + CopyStringFromDictionary(service_properties, flimflam::kNameProperty, + &config_properties); + CopyStringFromDictionary(service_properties, flimflam::kGuidProperty, + &config_properties); + if (type == flimflam::kTypeVPN) { + config_properties.SetStringWithoutPathExpansion( + flimflam::kProviderTypeProperty, vpn_provider_type); + config_properties.SetStringWithoutPathExpansion( + flimflam::kProviderHostProperty, vpn_provider_host); + } else if (type == flimflam::kTypeWifi) { + CopyStringFromDictionary(service_properties, flimflam::kSecurityProperty, + &config_properties); + } + network_configuration_handler_->SetProperties( service_path, config_properties, @@ -480,8 +510,14 @@ void NetworkConnectionHandler::VerifyConfiguredAndConnect( return; } - // Otherwise, we need to configure the network. - ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); + // Otherwise, we probably still need to configure the network since + // 'Connectable' is false. If |check_error_state| is true, signal an + // error, otherwise attempt to connect to possibly gain additional error + // state from Shill (or in case 'Connectable' is improperly unset). + if (check_error_state) + ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); + else + CallShillConnect(service_path); } void NetworkConnectionHandler::CallShillConnect( @@ -627,7 +663,7 @@ void NetworkConnectionHandler::CallShillDisconnect( base::Bind(&NetworkConnectionHandler::HandleShillDisconnectSuccess, AsWeakPtr(), service_path, success_callback), base::Bind(&network_handler::ShillErrorCallbackFunction, - kErrorDisconnectFailed, service_path, error_callback)); + kErrorShillError, service_path, error_callback)); } void NetworkConnectionHandler::HandleShillDisconnectSuccess( @@ -638,4 +674,29 @@ void NetworkConnectionHandler::HandleShillDisconnectSuccess( success_callback.Run(); } +// Activate + +void NetworkConnectionHandler::CallShillActivate( + const std::string& service_path, + const std::string& carrier, + const base::Closure& success_callback, + const network_handler::ErrorCallback& error_callback) { + NET_LOG_USER("Activate Request", service_path + ": '" + carrier + "'"); + DBusThreadManager::Get()->GetShillServiceClient()->ActivateCellularModem( + dbus::ObjectPath(service_path), + carrier, + base::Bind(&NetworkConnectionHandler::HandleShillActivateSuccess, + AsWeakPtr(), service_path, success_callback), + base::Bind(&network_handler::ShillErrorCallbackFunction, + kErrorShillError, service_path, error_callback)); +} + +void NetworkConnectionHandler::HandleShillActivateSuccess( + const std::string& service_path, + const base::Closure& success_callback) { + NET_LOG_EVENT("Activate Request Sent", service_path); + if (!success_callback.is_null()) + success_callback.Run(); +} + } // namespace chromeos diff --git a/chromeos/network/network_connection_handler.h b/chromeos/network/network_connection_handler.h index 8f00a8a..1dfca49 100644 --- a/chromeos/network/network_connection_handler.h +++ b/chromeos/network/network_connection_handler.h @@ -58,8 +58,7 @@ class CHROMEOS_EXPORT NetworkConnectionHandler static const char kErrorConfigurationRequired[]; static const char kErrorShillError[]; static const char kErrorConnectFailed[]; - static const char kErrorDisconnectFailed[]; - static const char kErrorMissingProviderType[]; + static const char kErrorMissingProvider[]; static const char kErrorUnknown[]; // Constants for |error_name| from |error_callback| for Disconnect. @@ -99,6 +98,18 @@ class CHROMEOS_EXPORT NetworkConnectionHandler const base::Closure& success_callback, const network_handler::ErrorCallback& error_callback); + // ActivateNetwork() will start an asynchronous activation attempt. + // |carrier| may be empty or may specify a carrier to activate. + // On success, |success_callback| will be called. + // On failure, |error_callback| will be called with |error_name| one of: + // kErrorNotFound if no network matching |service_path| is found. + // kErrorShillError if a DBus or Shill error occurred. + // TODO(stevenjb/armansito): Move this to a separate NetworkActivationHandler. + void ActivateNetwork(const std::string& service_path, + const std::string& carrier, + const base::Closure& success_callback, + const network_handler::ErrorCallback& error_callback); + // Returns true if ConnectToNetwork has been called with |service_path| and // has not completed (i.e. success or error callback has been called). bool HasConnectingNetwork(const std::string& service_path); @@ -163,10 +174,21 @@ class CHROMEOS_EXPORT NetworkConnectionHandler const base::Closure& success_callback, const network_handler::ErrorCallback& error_callback); - // Handle success or failure from Shill.Service.Disconnect. + // Handle success from Shill.Service.Disconnect. void HandleShillDisconnectSuccess(const std::string& service_path, const base::Closure& success_callback); + // Calls Shill.Manager.Activate asynchronously. + void CallShillActivate( + const std::string& service_path, + const std::string& carrier, + const base::Closure& success_callback, + const network_handler::ErrorCallback& error_callback); + + // Handle success from Shill.Service.ActivateCellularModem. + void HandleShillActivateSuccess(const std::string& service_path, + const base::Closure& success_callback); + // Local references to the associated handler instances. CertLoader* cert_loader_; NetworkStateHandler* network_state_handler_; diff --git a/chromeos/network/network_profile_handler.cc b/chromeos/network/network_profile_handler.cc index d209265..26b1bef 100644 --- a/chromeos/network/network_profile_handler.cc +++ b/chromeos/network/network_profile_handler.cc @@ -188,6 +188,16 @@ const NetworkProfile* NetworkProfileHandler::GetProfileForUserhash( return NULL; } +const NetworkProfile* NetworkProfileHandler::GetDefaultUserProfile() const { + for (NetworkProfileHandler::ProfileList::const_iterator it = + profiles_.begin(); + it != profiles_.end(); ++it) { + if (!it->userhash.empty()) + return &*it; + } + return NULL; +} + NetworkProfileHandler::NetworkProfileHandler() : network_state_handler_(NULL), weak_ptr_factory_(this) { diff --git a/chromeos/network/network_profile_handler.h b/chromeos/network/network_profile_handler.h index d3c784e..15bb0fd 100644 --- a/chromeos/network/network_profile_handler.h +++ b/chromeos/network/network_profile_handler.h @@ -52,6 +52,11 @@ class CHROMEOS_EXPORT NetworkProfileHandler const NetworkProfile* GetProfileForUserhash( const std::string& userhash) const; + // Returns the first profile entry with a non-empty userhash. + // TODO(stevenjb): Replace with GetProfileForUserhash() with the correct + // userhash. + const NetworkProfile* GetDefaultUserProfile() const; + static const char kSharedProfilePath[]; protected: diff --git a/chromeos/network/network_state.cc b/chromeos/network/network_state.cc index f0da62d..c196473 100644 --- a/chromeos/network/network_state.cc +++ b/chromeos/network/network_state.cc @@ -13,7 +13,6 @@ #include "base/strings/utf_string_conversion_utils.h" #include "chromeos/network/network_event_log.h" #include "chromeos/network/network_profile_handler.h" -#include "chromeos/network/network_ui_data.h" #include "chromeos/network/network_util.h" #include "chromeos/network/onc/onc_utils.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -51,23 +50,6 @@ std::string ValidateUTF8(const std::string& str) { return result; } -// Returns a new NetworkUIData* if |ui_data_value| is a valid NetworkUIData -// dictionary string, otherwise returns NULL. -chromeos::NetworkUIData* CreateUIDataFromValue( - const base::Value& ui_data_value) { - std::string ui_data_str; - if (!ui_data_value.GetAsString(&ui_data_str)) - return NULL; - if (ui_data_str.empty()) - return new chromeos::NetworkUIData(); - - scoped_ptr<base::DictionaryValue> ui_data_dict( - chromeos::onc::ReadDictionaryFromJson(ui_data_str)); - if (!ui_data_dict) - return NULL; - return new chromeos::NetworkUIData(*ui_data_dict); -} - bool IsCaCertNssSet(const base::DictionaryValue& properties) { std::string ca_cert_nss; if (properties.GetStringWithoutPathExpansion(flimflam::kEapCaCertNssProperty, @@ -104,7 +86,6 @@ NetworkState::NetworkState(const std::string& path) auto_connect_(false), favorite_(false), priority_(0), - onc_source_(onc::ONC_SOURCE_NONE), prefix_length_(0), signal_strength_(0), connectable_(false), @@ -180,7 +161,7 @@ bool NetworkState::PropertyChanged(const std::string& key, } return true; } else if (key == flimflam::kUIDataProperty) { - if (!GetOncSource(value, &onc_source_)) { + if (!GetUIDataFromValue(value, &ui_data_)) { NET_LOG_ERROR("Failed to parse " + key, path()); return false; } @@ -310,8 +291,8 @@ bool NetworkState::IsConnectingState() const { } bool NetworkState::IsManaged() const { - return onc_source_ == onc::ONC_SOURCE_DEVICE_POLICY || - onc_source_ == onc::ONC_SOURCE_USER_POLICY; + return ui_data_.onc_source() == onc::ONC_SOURCE_DEVICE_POLICY || + ui_data_.onc_source() == onc::ONC_SOURCE_USER_POLICY; } bool NetworkState::IsPrivate() const { @@ -432,12 +413,20 @@ std::string NetworkState::IPConfigProperty(const char* key) { } // static -bool NetworkState::GetOncSource(const base::Value& ui_data_value, - onc::ONCSource* out) { - scoped_ptr<NetworkUIData> ui_data(CreateUIDataFromValue(ui_data_value)); - if (!ui_data) +bool NetworkState::GetUIDataFromValue(const base::Value& ui_data_value, + NetworkUIData* out) { + std::string ui_data_str; + if (!ui_data_value.GetAsString(&ui_data_str)) + return false; + if (ui_data_str.empty()) { + *out = NetworkUIData(); + return true; + } + scoped_ptr<base::DictionaryValue> ui_data_dict( + chromeos::onc::ReadDictionaryFromJson(ui_data_str)); + if (!ui_data_dict) return false; - *out = ui_data->onc_source(); + *out = NetworkUIData(*ui_data_dict); return true; } diff --git a/chromeos/network/network_state.h b/chromeos/network/network_state.h index f177794..d6ec612 100644 --- a/chromeos/network/network_state.h +++ b/chromeos/network/network_state.h @@ -10,6 +10,7 @@ #include "base/values.h" #include "chromeos/network/managed_state.h" +#include "chromeos/network/network_ui_data.h" #include "chromeos/network/onc/onc_constants.h" namespace chromeos { @@ -50,7 +51,7 @@ class CHROMEOS_EXPORT NetworkState : public ManagedState { bool favorite() const { return favorite_; } int priority() const { return priority_; } const base::DictionaryValue& proxy_config() const { return proxy_config_; } - onc::ONCSource onc_source() const { return onc_source_; } + const NetworkUIData& ui_data() const { return ui_data_; } // IPConfig Properties const std::string& ip_address() const { return ip_address_; } const std::string& gateway() const { return gateway_; } @@ -90,7 +91,7 @@ class CHROMEOS_EXPORT NetworkState : public ManagedState { // Returns a comma separated string of name servers. std::string GetDnsServersAsString() const; - // Converts the prefix length to a netmaks string. + // Converts the prefix length to a network string. std::string GetNetmask() const; // Helpers (used e.g. when a state is cached) @@ -101,9 +102,9 @@ class CHROMEOS_EXPORT NetworkState : public ManagedState { // key. static std::string IPConfigProperty(const char* key); - // Sets |out| to the ONCSource specified by the UIData property |value|. - // Returns true if the source was successfully parsed. - static bool GetOncSource(const base::Value& value, onc::ONCSource* out); + // Sets |out| to the UIData specified by |value|. Returns true if successfully + // parsed. + static bool GetUIDataFromValue(const base::Value& value, NetworkUIData* out); // Generates a name from properties."Wifi.HexSSID" if present, otherwise // validates properties.Name and returns a valid utf8 version. @@ -134,7 +135,7 @@ class CHROMEOS_EXPORT NetworkState : public ManagedState { // TODO(pneubeck): Remove ProxyConfig once NetworkConfigurationHandler // provides proxy configuration. crbug/241775 base::DictionaryValue proxy_config_; - onc::ONCSource onc_source_; + NetworkUIData ui_data_; // IPConfig properties. // Note: These do not correspond to actual Shill.Service properties // but are derived from the service's corresponding IPConfig object. |