| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROMEOS_NETWORK_NETWORK_STATE_HANDLER_H_ |
| #define CHROMEOS_NETWORK_NETWORK_STATE_HANDLER_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/callback_forward.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/macros.h" |
| #include "base/observer_list.h" |
| #include "base/sequence_checker.h" |
| #include "chromeos/chromeos_export.h" |
| #include "chromeos/network/managed_state.h" |
| #include "chromeos/network/network_handler.h" |
| #include "chromeos/network/network_handler_callbacks.h" |
| #include "chromeos/network/network_type_pattern.h" |
| #include "chromeos/network/shill_property_handler.h" |
| |
| namespace base { |
| class DictionaryValue; |
| class ListValue; |
| class Location; |
| class Value; |
| } |
| |
| namespace chromeos { |
| |
| class DeviceState; |
| class NetworkState; |
| class NetworkStateHandlerObserver; |
| class NetworkStateHandlerTest; |
| |
| // Class for tracking the list of visible networks and their properties. |
| // |
| // This class maps essential properties from the connection manager (Shill) for |
| // each visible network. It is not used to change the properties of services or |
| // devices, only global (manager) properties. |
| // |
| // All getters return the currently cached properties. This class is expected to |
| // keep properties up to date by managing the appropriate Shill observers. |
| // It will invoke its own more specific observer methods when the specified |
| // changes occur. |
| // |
| // Some notes about NetworkState and GUIDs: |
| // * A NetworkState exists for all network services stored in a profile, and |
| // all "visible" networks (physically connected networks like ethernet and |
| // cellular or in-range wifi networks). If the network is stored in a profile, |
| // NetworkState.IsInProfile() will return true. |
| // * "Visible" networks return true for NetworkState.visible(). |
| // * All networks saved to a profile will have a saved GUID that is persistent |
| // across sessions. |
| // * Networks that are not saved to a profile will have a GUID assigned when |
| // the initial properties are received. The GUID will be consistent for |
| // the duration of a session, even if the network drops out and returns. |
| |
| class CHROMEOS_EXPORT NetworkStateHandler |
| : public internal::ShillPropertyHandler::Listener { |
| public: |
| typedef std::vector<std::unique_ptr<ManagedState>> ManagedStateList; |
| typedef std::vector<const NetworkState*> NetworkStateList; |
| typedef std::vector<const DeviceState*> DeviceStateList; |
| |
| class TetherSortDelegate { |
| public: |
| // Sorts |tether_networks| according to the Tether component rules. |
| // |tether_networks| contains only networks of type Tether. |
| virtual void SortTetherNetworkList( |
| ManagedStateList* tether_networks) const = 0; |
| }; |
| |
| enum TechnologyState { |
| TECHNOLOGY_UNAVAILABLE, |
| TECHNOLOGY_AVAILABLE, |
| TECHNOLOGY_UNINITIALIZED, |
| TECHNOLOGY_ENABLING, |
| TECHNOLOGY_ENABLED, |
| TECHNOLOGY_PROHIBITED |
| }; |
| |
| ~NetworkStateHandler() override; |
| |
| // Called just before destruction to give observers a chance to remove |
| // themselves and disable any networking. |
| void Shutdown(); |
| |
| // Add/remove observers. |
| void AddObserver(NetworkStateHandlerObserver* observer, |
| const base::Location& from_here); |
| void RemoveObserver(NetworkStateHandlerObserver* observer, |
| const base::Location& from_here); |
| |
| // Returns the state for technology |type|. Only |
| // NetworkTypePattern::Primitive, ::Mobile, ::Ethernet, and ::Tether are |
| // supported. |
| TechnologyState GetTechnologyState(const NetworkTypePattern& type) const; |
| bool IsTechnologyAvailable(const NetworkTypePattern& type) const { |
| return GetTechnologyState(type) != TECHNOLOGY_UNAVAILABLE; |
| } |
| bool IsTechnologyEnabled(const NetworkTypePattern& type) const { |
| return GetTechnologyState(type) == TECHNOLOGY_ENABLED; |
| } |
| bool IsTechnologyProhibited(const NetworkTypePattern& type) const { |
| return GetTechnologyState(type) == TECHNOLOGY_PROHIBITED; |
| } |
| bool IsTechnologyUninitialized(const NetworkTypePattern& type) const { |
| return GetTechnologyState(type) == TECHNOLOGY_UNINITIALIZED; |
| } |
| |
| // Asynchronously sets the technology enabled property for |type|. Only |
| // NetworkTypePattern::Primitive, ::Mobile and ::Ethernet are supported. |
| // Note: Modifies Manager state. Calls |error_callback| on failure. |
| void SetTechnologyEnabled( |
| const NetworkTypePattern& type, |
| bool enabled, |
| const network_handler::ErrorCallback& error_callback); |
| |
| // Sets the Tether technology state. Because Tether networks do not represent |
| // real Shill networks, this value must be set by the Tether component rather |
| // than being generated by Shill. See TetherDeviceStateManager for more |
| // details. |
| void SetTetherTechnologyState(TechnologyState technology_state); |
| |
| // Sets the scanning state of the Tether technology. Since Tether network |
| // scans are not actually performed as part of Shill, this value must be set |
| // by the Tether component. |
| void SetTetherScanState(bool is_scanning); |
| |
| // Asynchronously sets the list of prohibited technologies. The accepted |
| // values are the shill network technology identifiers. See also |
| // chromeos::onc::Validator::ValidateGlobalNetworkConfiguration(). |
| void SetProhibitedTechnologies( |
| const std::vector<std::string>& prohibited_technologies, |
| const network_handler::ErrorCallback& error_callback); |
| |
| // Finds and returns a device state by |device_path| or NULL if not found. |
| const DeviceState* GetDeviceState(const std::string& device_path) const; |
| |
| // Finds and returns a device state by |type|. Returns NULL if not found. |
| const DeviceState* GetDeviceStateByType(const NetworkTypePattern& type) const; |
| |
| // Returns true if any device of |type| is scanning. |
| bool GetScanningByType(const NetworkTypePattern& type) const; |
| |
| // Finds and returns a network state by |service_path| or NULL if not found. |
| // Note: NetworkState is frequently updated asynchronously, i.e. properties |
| // are not always updated all at once. This will contain the most recent |
| // value for each property. To receive notifications when a property changes, |
| // observe this class and implement NetworkPropertyChanged(). |
| const NetworkState* GetNetworkState(const std::string& service_path) const; |
| |
| // Returns the default network (which includes VPNs) based on the Shill |
| // Manager.DefaultNetwork property. Normally this is the same as |
| // ConnectedNetworkByType(NetworkTypePattern::Default()), but the timing might |
| // differ. |
| const NetworkState* DefaultNetwork() const; |
| |
| // Returns the primary connected network of matching |type|, otherwise NULL. |
| const NetworkState* ConnectedNetworkByType(const NetworkTypePattern& type); |
| |
| // Like ConnectedNetworkByType() but returns a connecting network or NULL. |
| const NetworkState* ConnectingNetworkByType( |
| const NetworkTypePattern& type) const; |
| |
| // Like ConnectedNetworkByType() but returns any matching visible network or |
| // NULL. Mostly useful for mobile networks where there is generally only one |
| // network. Note: O(N). |
| const NetworkState* FirstNetworkByType(const NetworkTypePattern& type); |
| |
| // Returns the aa:bb formatted hardware (MAC) address for the first connected |
| // network matching |type|, or an empty string if none is connected. |
| std::string FormattedHardwareAddressForType(const NetworkTypePattern& type); |
| |
| // Convenience method to call GetNetworkListByType(visible=true). |
| void GetVisibleNetworkListByType(const NetworkTypePattern& type, |
| NetworkStateList* list); |
| |
| // Convenience method for GetVisibleNetworkListByType(Default). |
| void GetVisibleNetworkList(NetworkStateList* list); |
| |
| // Sets |list| to contain the list of networks with matching |type| and the |
| // following properties: |
| // |configured_only| - if true only include networks where IsInProfile is true |
| // |visible_only| - if true only include networks in the visible Services list |
| // |limit| - if > 0 limits the number of results. |
| // The returned list contains a copy of NetworkState pointers which should not |
| // be stored or used beyond the scope of the calling function (i.e. they may |
| // later become invalid, but only on the UI thread). SortNetworkList() will be |
| // called if necessary to provide the states in a convenient order (see |
| // SortNetworkList for details). |
| void GetNetworkListByType(const NetworkTypePattern& type, |
| bool configured_only, |
| bool visible_only, |
| size_t limit, |
| NetworkStateList* list); |
| |
| // Finds and returns the NetworkState associated with |service_path| or NULL |
| // if not found. If |configured_only| is true, only returns saved entries |
| // (IsInProfile is true). |
| const NetworkState* GetNetworkStateFromServicePath( |
| const std::string& service_path, |
| bool configured_only) const; |
| |
| // Finds and returns the NetworkState associated with |guid| or NULL if not |
| // found. This returns all entries (IsInProfile() may be true or false). |
| const NetworkState* GetNetworkStateFromGuid(const std::string& guid) const; |
| |
| // Creates a Tether NetworkState that has no underlying shill type or |
| // service. When initially created, it does not actually represent a real |
| // network. The |guid| provided must be non-empty. If a network with |guid| |
| // already exists, this method will do nothing. Use the provided |guid| to |
| // refer to and fetch this NetworkState in the future. Note that the |
| // |has_connected_to_host| parameter refers to whether the current device has |
| // already connected to the Tether host device providing this Tether network |
| // in the past. |
| void AddTetherNetworkState(const std::string& guid, |
| const std::string& name, |
| const std::string& carrier, |
| int battery_percentage, |
| int signal_strength, |
| bool has_connected_to_host); |
| |
| // Updates the Tether properties (carrier, battery percentage, and signal |
| // strength) for a network which has already been added via |
| // AddTetherNetworkState. Returns whether the update was successful. |
| bool UpdateTetherNetworkProperties(const std::string& guid, |
| const std::string& carrier, |
| int battery_percentage, |
| int signal_strength); |
| |
| // Updates whether the Tether network with GUID |guid| has connected to the |
| // host device before, setting the value to true. Note that there is no way to |
| // change this value back to false. If no network with GUID |guid| is |
| // registered or if the network is registered and its HasConnectedToHost value |
| // was already true, this function does nothing. Returns whether the value was |
| // actually changed. |
| bool SetTetherNetworkHasConnectedToHost(const std::string& guid); |
| |
| // Remove a Tether NetworkState, using the same |guid| passed to |
| // AddTetherNetworkState(). If no network with GUID |guid| is registered, this |
| // function does nothing. Returns whether the network was actually removed. |
| bool RemoveTetherNetworkState(const std::string& guid); |
| |
| // Disassociates the Tether network specified by |tether_network_guid| from |
| // its associated Wi-Fi network. Returns whether the networkd were |
| // successfully disassociated. |
| bool DisassociateTetherNetworkStateFromWifiNetwork( |
| const std::string& tether_network_guid); |
| |
| // Inform NetworkStateHandler that the provided Tether network with the |
| // provided guid |tether_network_guid| is associated with the Wi-Fi network |
| // with the provided guid |wifi_network_guid|. This Wi-Fi network can now be |
| // hidden in the UI, and the Tether network will act as its proxy. Returns |
| // false if the association failed (e.g., one or both networks don't exist). |
| bool AssociateTetherNetworkStateWithWifiNetwork( |
| const std::string& tether_network_guid, |
| const std::string& wifi_network_guid); |
| |
| // Set the connection_state of the Tether NetworkState corresponding to the |
| // provided |guid| to "Disconnected". This will be reflected in the UI. |
| void SetTetherNetworkStateDisconnected(const std::string& guid); |
| |
| // Set the connection_state of the Tether NetworkState corresponding to the |
| // provided |guid| to "Connecting". This will be reflected in the UI. |
| void SetTetherNetworkStateConnecting(const std::string& guid); |
| |
| // Set the connection_state of the Tether NetworkState corresponding to the |
| // provided |guid| to "Connected". This will be reflected in the UI. |
| void SetTetherNetworkStateConnected(const std::string& guid); |
| |
| void set_tether_sort_delegate( |
| const TetherSortDelegate* tether_sort_delegate) { |
| tether_sort_delegate_ = tether_sort_delegate; |
| } |
| |
| // Sets |list| to contain the list of devices. The returned list contains |
| // a copy of DeviceState pointers which should not be stored or used beyond |
| // the scope of the calling function (i.e. they may later become invalid, but |
| // only on the UI thread). |
| void GetDeviceList(DeviceStateList* list) const; |
| |
| // Like GetDeviceList() but only returns networks with matching |type|. |
| void GetDeviceListByType(const NetworkTypePattern& type, |
| DeviceStateList* list) const; |
| |
| // Requests a network scan. This may trigger updates to the network |
| // list, which will trigger the appropriate observer calls. If |type| is |
| // Cellular, a mobile network scan will be requested if supported. |
| void RequestScan(const NetworkTypePattern& type); |
| |
| // Requests an update for an existing NetworkState, e.g. after configuring |
| // a network. This is a no-op if an update request is already pending. To |
| // ensure that a change is picked up, this must be called after Shill |
| // acknowledged it (e.g. in the callback of a SetProperties). |
| // When the properties are received, NetworkPropertiesUpdated will be |
| // signaled for each member of |observers_|, regardless of whether any |
| // properties actually changed. Note that this is a no-op for Tether networks. |
| void RequestUpdateForNetwork(const std::string& service_path); |
| |
| // Informs NetworkStateHandler to notify observers that the properties for |
| // the network may have changed. Called e.g. when the proxy properties may |
| // have changed. |
| void SendUpdateNotificationForNetwork(const std::string& service_path); |
| |
| // Clears the last_error value for the NetworkState for |service_path|. |
| void ClearLastErrorForNetwork(const std::string& service_path); |
| |
| // Sets the list of devices on which portal check is enabled. |
| void SetCheckPortalList(const std::string& check_portal_list); |
| |
| // Sets the Manager.WakeOnLan property. Note: we do not track this state, we |
| // only set it. |
| void SetWakeOnLanEnabled(bool enabled); |
| |
| // Sets the HostName property. Note: we do not track this property, we |
| // only set it. |
| void SetHostname(const std::string& hostname); |
| |
| // Enable or disable network bandwidth throttling, on all interfaces on the |
| // system. If |enabled| is true, |upload_rate_kbits| and |download_rate_kbits| |
| // are the desired rates (in kbits/s) to throttle to. If |enabled| is false, |
| // throttling is off, and the rates are ignored. |
| void SetNetworkThrottlingStatus(bool enabled, |
| uint32_t upload_rate_kbits, |
| uint32_t download_rate_kbits); |
| |
| const std::string& GetCheckPortalListForTest() const { |
| return check_portal_list_; |
| } |
| |
| // Returns the NetworkState of the EthernetEAP service, which contains the |
| // EAP parameters used by the ethernet with |service_path|. If |service_path| |
| // doesn't refer to an ethernet service or if the ethernet service is not |
| // connected using EAP, returns NULL. |
| const NetworkState* GetEAPForEthernet(const std::string& service_path); |
| |
| const std::string& default_network_path() const { |
| return default_network_path_; |
| } |
| |
| // Sets the |last_error_| property of the matching NetworkState for tests. |
| void SetLastErrorForTest(const std::string& service_path, |
| const std::string& error); |
| |
| // Constructs and initializes an instance for testing. |
| static std::unique_ptr<NetworkStateHandler> InitializeForTest(); |
| |
| // Default set of comma separated interfaces on which to enable |
| // portal checking. |
| static const char kDefaultCheckPortalList[]; |
| |
| protected: |
| friend class NetworkHandler; |
| NetworkStateHandler(); |
| |
| // ShillPropertyHandler::Listener overrides. |
| |
| // This adds new entries to |network_list_| or |device_list_| and deletes any |
| // entries that are no longer in the list. |
| void UpdateManagedList(ManagedState::ManagedType type, |
| const base::ListValue& entries) override; |
| |
| // The list of profiles changed (i.e. a user has logged in). Re-request |
| // properties for all services since they may have changed. |
| void ProfileListChanged() override; |
| |
| // Parses the properties for the network service or device. Mostly calls |
| // managed->PropertyChanged(key, value) for each dictionary entry. |
| void UpdateManagedStateProperties( |
| ManagedState::ManagedType type, |
| const std::string& path, |
| const base::DictionaryValue& properties) override; |
| |
| // Called by ShillPropertyHandler when a watched service property changes. |
| void UpdateNetworkServiceProperty(const std::string& service_path, |
| const std::string& key, |
| const base::Value& value) override; |
| |
| // Called by ShillPropertyHandler when a watched device property changes. |
| void UpdateDeviceProperty(const std::string& device_path, |
| const std::string& key, |
| const base::Value& value) override; |
| |
| // Called by ShillPropertyHandler when a watched network or device |
| // IPConfig property changes. |
| void UpdateIPConfigProperties( |
| ManagedState::ManagedType type, |
| const std::string& path, |
| const std::string& ip_config_path, |
| const base::DictionaryValue& properties) override; |
| |
| // Called by ShillPropertyHandler when the portal check list manager property |
| // changes. |
| void CheckPortalListChanged(const std::string& check_portal_list) override; |
| |
| // Called by ShillPropertyHandler when a technology list changes. |
| void TechnologyListChanged() override; |
| |
| // Called by |shill_property_handler_| when the service or device list has |
| // changed and all entries have been updated. This updates the list and |
| // notifies observers. |
| void ManagedStateListChanged(ManagedState::ManagedType type) override; |
| |
| // Called when the default network service changes. Sets default_network_path_ |
| // and notifies listeners. |
| void DefaultNetworkServiceChanged(const std::string& service_path) override; |
| |
| // Called after construction. Called explicitly by tests after adding |
| // test observers. |
| void InitShillPropertyHandler(); |
| |
| private: |
| typedef std::map<std::string, std::string> SpecifierGuidMap; |
| friend class NetworkStateHandlerTest; |
| FRIEND_TEST_ALL_PREFIXES(NetworkStateHandlerTest, NetworkStateHandlerStub); |
| |
| // Sorts the network list. Called when all network updates have been received, |
| // or when the network list is requested but the list is in an unsorted state. |
| // Networks are sorted as follows, maintaining the existing relative ordering: |
| // * Connected or connecting networks (should be listed first by Shill) |
| // * Visible non-wifi networks |
| // * Visible wifi networks |
| // * Hidden (wifi) networks |
| // If |ensure_cellular| is true, call EnsureCellularNetwork (which may |
| // remove a network from the list). |
| void SortNetworkList(bool ensure_cellular); |
| |
| // Updates UMA stats. Called once after all requested networks are updated. |
| void UpdateNetworkStats(); |
| |
| // NetworkState specific method for UpdateManagedStateProperties which |
| // notifies observers. |
| void UpdateNetworkStateProperties(NetworkState* network, |
| const base::DictionaryValue& properties); |
| |
| // Ensure a valid GUID for NetworkState. |
| void UpdateGuid(NetworkState* network); |
| |
| // Cellular networks may not have an associated Shill Service (e.g. when the |
| // SIM is locked or a mobile network is not available). To simplify the UI, |
| // if a Cellular Device exists |cellular_networks| will be modified to contain |
| // exactly one network, creating a default network if necessary. |
| void EnsureCellularNetwork(ManagedStateList* cellular_networks); |
| |
| // Sends NetworkListChanged() to observers and logs an event. |
| void NotifyNetworkListChanged(); |
| |
| // Sends DeviceListChanged() to observers and logs an event. |
| void NotifyDeviceListChanged(); |
| |
| // Non-const getters for managed entries. These are const so that they can |
| // be called by Get[Network|Device]State, even though they return non-const |
| // pointers. |
| DeviceState* GetModifiableDeviceState(const std::string& device_path) const; |
| NetworkState* GetModifiableNetworkState( |
| const std::string& service_path) const; |
| NetworkState* GetModifiableNetworkStateFromGuid( |
| const std::string& guid) const; |
| ManagedState* GetModifiableManagedState(const ManagedStateList* managed_list, |
| const std::string& path) const; |
| |
| // Gets the list specified by |type|. |
| ManagedStateList* GetManagedList(ManagedState::ManagedType type); |
| |
| // Helper function that calls NotifyNetworkConnectionStateChanged and, |
| // for the default network, OnDefaultNetworkConnectionStateChanged and |
| // NotifyDefaultNetworkChanged. |
| void OnNetworkConnectionStateChanged(NetworkState* network); |
| |
| // Verifies the connection state of the default network. Returns false |
| // if the connection state change should be ignored. |
| bool VerifyDefaultNetworkConnectionStateChange(NetworkState* network); |
| |
| // Notifies observers when a network's connection state changes. |
| void NotifyNetworkConnectionStateChanged(NetworkState* network); |
| |
| // Notifies observers when the default network or its properties change. |
| void NotifyDefaultNetworkChanged(); |
| |
| // Notifies observers about changes to |network|, including IPConfg. |
| void NotifyNetworkPropertiesUpdated(const NetworkState* network); |
| |
| // Notifies observers about changes to |device|, including IPConfigs. |
| void NotifyDevicePropertiesUpdated(const DeviceState* device); |
| |
| // Called to ask observers to scan for networks. |
| void NotifyScanRequested(); |
| |
| // Called whenever Device.Scanning state transitions to false. |
| void NotifyScanCompleted(const DeviceState* device); |
| |
| // Helper function to log property updated events. |
| void LogPropertyUpdated(const ManagedState* network, |
| const std::string& key, |
| const base::Value& value); |
| |
| // Returns one technology type for |type|. This technology will be the |
| // highest priority technology in the type pattern. |
| std::string GetTechnologyForType(const NetworkTypePattern& type) const; |
| |
| // Returns all the technology types for |type|. |
| std::vector<std::string> GetTechnologiesForType( |
| const NetworkTypePattern& type) const; |
| |
| // Adds Tether networks to |list|, limiting the maximum size of |list| to be |
| // |limit|. If |get_active| is true, only active (i.e., connecting/connected) |
| // networks will be added; otherwise, only inactive networks will be added. |
| // The returned list contains a copy of NetworkState pointers which |
| // should not be stored or used beyond the scope of the calling |
| // function (i.e., they may later become invalid, but only on the UI thread). |
| // See AddTetherNetworkState() for more information about Tether networks. |
| void AppendTetherNetworksToList(bool get_active, |
| size_t limit, |
| NetworkStateList* list); |
| |
| // Set the connection_state of a Tether NetworkState corresponding to the |
| // provided |guid|. |
| void SetTetherNetworkStateConnectionState( |
| const std::string& guid, |
| const std::string& connection_state); |
| |
| // Ensures that the Tether DeviceState is present in |device_list_| if |
| // |tether_technology_state_| is not TECHNOLOGY_UNAVAILABLE and ensures that |
| // it is not present in |device_list_| if it is TECHNOLOGY_UNAVAILABLE. |
| void EnsureTetherDeviceState(); |
| |
| // Shill property handler instance, owned by this class. |
| std::unique_ptr<internal::ShillPropertyHandler> shill_property_handler_; |
| |
| // Observer list |
| base::ObserverList<NetworkStateHandlerObserver, true> observers_; |
| |
| // List of managed network states |
| ManagedStateList network_list_; |
| |
| // List of managed Tether network states, which exist separately from |
| // |network_list_|. |
| ManagedStateList tether_network_list_; |
| |
| // Set to true when the network list is sorted, cleared when network updates |
| // arrive. Used to trigger sorting when needed. |
| bool network_list_sorted_ = false; |
| |
| // List of managed device states |
| ManagedStateList device_list_; |
| |
| // Keeps track of the default network for notifying observers when it changes. |
| std::string default_network_path_; |
| |
| // List of interfaces on which portal check is enabled. |
| std::string check_portal_list_; |
| |
| // Map of network specifiers to guids. Contains an entry for each |
| // NetworkState that is not saved in a profile. |
| SpecifierGuidMap specifier_guid_map_; |
| |
| // The state corresponding to the Tether device type. This value is managed by |
| // the Tether component. |
| TechnologyState tether_technology_state_ = |
| TechnologyState::TECHNOLOGY_UNAVAILABLE; |
| |
| // Not owned by this instance. |
| const TetherSortDelegate* tether_sort_delegate_ = nullptr; |
| |
| // Ensure that Shutdown() gets called exactly once. |
| bool did_shutdown_ = false; |
| |
| // Ensure that we do not delete any networks while notifying observers. |
| bool notifying_network_observers_ = false; |
| |
| SEQUENCE_CHECKER(sequence_checker_); |
| |
| DISALLOW_COPY_AND_ASSIGN(NetworkStateHandler); |
| }; |
| |
| } // namespace chromeos |
| |
| #endif // CHROMEOS_NETWORK_NETWORK_STATE_HANDLER_H_ |