diff options
author | pneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-19 21:31:34 +0000 |
---|---|---|
committer | pneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-19 21:31:34 +0000 |
commit | 21dc5ec7a3c65a78bb6e4047eba6ddac68d9e2e7 (patch) | |
tree | 580714e1a5bb49aea0d49f9acf7e27af4ca07e1e | |
parent | 511833408f73cacc044db20a5e8bb57bdc329e14 (diff) | |
download | chromium_src-21dc5ec7a3c65a78bb6e4047eba6ddac68d9e2e7.zip chromium_src-21dc5ec7a3c65a78bb6e4047eba6ddac68d9e2e7.tar.gz chromium_src-21dc5ec7a3c65a78bb6e4047eba6ddac68d9e2e7.tar.bz2 |
Fixed proxy settings in case of simultaneously active device and user ONC policy.
This fix required the following changes:
- Let Shill emit profile and proxy config changes.
(see https://gerrit.chromium.org/gerrit/#/c/37935/)
The active network's changes are automatically picked up by ProxyConfigTracker.
- Make NetworkConfigurationUpdater an observer of the Manager's profile list (by
implementing the new NetworkLibrary::NetworkProfileObserver class), so that
the user policy is applied _after_ Shill has pushed the user profile.
- Ensure in the NetworkConfigurationUpdater that the device policy is always
overwritten by the user policy (if the former is applied, also apply the
latter).
Apart from that, I cleaned up the code a little bit. E.g. the following members of NetworkLibrary were unused:
- FindRememberedNetworkByUniqueId
- SetNetworkProfile
- remembered_network_unique_id_map_
BUG=157642
TEST=
- Setup both policies for the same SSID with different proxy settings.
- Check that after login the right proxy is used.
- Toggle AutoConnect of the device policy and reload the policy while still logged in.
- Check that still the right proxy is used.
Review URL: https://chromiumcodereview.appspot.com/11365225
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@168608 0039d316-1c4b-4281-b951-d872f2087c98
11 files changed, 278 insertions, 215 deletions
diff --git a/chrome/browser/chromeos/cros/cros_mock.cc b/chrome/browser/chromeos/cros/cros_mock.cc index 116f8f9..675542c 100644 --- a/chrome/browser/chromeos/cros/cros_mock.cc +++ b/chrome/browser/chromeos/cros/cros_mock.cc @@ -72,12 +72,16 @@ void CrosMock::SetStatusAreaMocksExpectations() { void CrosMock::SetNetworkLibraryStatusAreaExpectations() { // We don't care how often these are called, just set their return values: + EXPECT_CALL(*mock_network_library_, AddNetworkProfileObserver(_)) + .Times(AnyNumber()); EXPECT_CALL(*mock_network_library_, AddNetworkManagerObserver(_)) .Times(AnyNumber()); EXPECT_CALL(*mock_network_library_, AddNetworkDeviceObserver(_, _)) .Times(AnyNumber()); EXPECT_CALL(*mock_network_library_, AddCellularDataPlanObserver(_)) .Times(AnyNumber()); + EXPECT_CALL(*mock_network_library_, RemoveNetworkProfileObserver(_)) + .Times(AnyNumber()); EXPECT_CALL(*mock_network_library_, RemoveNetworkManagerObserver(_)) .Times(AnyNumber()); EXPECT_CALL(*mock_network_library_, RemoveNetworkDeviceObserver(_, _)) diff --git a/chrome/browser/chromeos/cros/mock_network_library.h b/chrome/browser/chromeos/cros/mock_network_library.h index 558d204..cc444769 100644 --- a/chrome/browser/chromeos/cros/mock_network_library.h +++ b/chrome/browser/chromeos/cros/mock_network_library.h @@ -20,6 +20,8 @@ class MockNetworkLibrary : public NetworkLibrary { MOCK_METHOD0(Init, void(void)); MOCK_CONST_METHOD0(IsCros, bool(void)); + MOCK_METHOD1(AddNetworkProfileObserver, void(NetworkProfileObserver*)); + MOCK_METHOD1(RemoveNetworkProfileObserver, void(NetworkProfileObserver*)); MOCK_METHOD1(AddNetworkManagerObserver, void(NetworkManagerObserver*)); MOCK_METHOD1(RemoveNetworkManagerObserver, void(NetworkManagerObserver*)); MOCK_METHOD2(AddNetworkObserver, void(const std::string&, NetworkObserver*)); @@ -95,8 +97,6 @@ class MockNetworkLibrary : public NetworkLibrary { MOCK_CONST_METHOD1(FindVirtualNetworkByPath, VirtualNetwork*(const std::string&)); MOCK_CONST_METHOD1(FindRememberedNetworkByPath, Network*(const std::string&)); - MOCK_CONST_METHOD1(FindRememberedNetworkByUniqueId, - Network*(const std::string&)); MOCK_CONST_METHOD1(FindOncForNetwork, const base::DictionaryValue*( const std::string& unique_id)); @@ -145,8 +145,6 @@ class MockNetworkLibrary : public NetworkLibrary { MOCK_METHOD1(DisconnectFromNetwork, void(const Network*)); MOCK_METHOD1(ForgetNetwork, void(const std::string&)); - MOCK_METHOD2(SetNetworkProfile, void(const std::string&, - NetworkProfileType)); MOCK_CONST_METHOD0(GetCellularHomeCarrierId, const std::string&(void)); MOCK_CONST_METHOD0(ethernet_available, bool(void)); diff --git a/chrome/browser/chromeos/cros/network_library.h b/chrome/browser/chromeos/cros/network_library.h index 93b1286..73e710e 100644 --- a/chrome/browser/chromeos/cros/network_library.h +++ b/chrome/browser/chromeos/cros/network_library.h @@ -1263,13 +1263,21 @@ class NetworkLibrary { USE_DHCP_GATEWAY), }; + class NetworkProfileObserver { + public: + // Called when the list of network profiles was changed. + virtual void OnProfileListChanged() = 0; + protected: + virtual ~NetworkProfileObserver() {} + }; + class NetworkManagerObserver { public: // Called when the state of the network manager has changed, // for example, networks have appeared or disappeared. virtual void OnNetworkManagerChanged(NetworkLibrary* obj) = 0; protected: - virtual ~NetworkManagerObserver() { } + virtual ~NetworkManagerObserver() {} }; class NetworkObserver { @@ -1334,6 +1342,10 @@ class NetworkLibrary { // Returns true if libcros was loaded instead of stubbed out. virtual bool IsCros() const = 0; + virtual void AddNetworkProfileObserver(NetworkProfileObserver* observer) = 0; + virtual void RemoveNetworkProfileObserver( + NetworkProfileObserver* observer) = 0; + virtual void AddNetworkManagerObserver(NetworkManagerObserver* observer) = 0; virtual void RemoveNetworkManagerObserver( NetworkManagerObserver* observer) = 0; @@ -1514,8 +1526,6 @@ class NetworkLibrary { // Return a pointer to the remembered network, if it exists, or NULL. virtual Network* FindRememberedNetworkByPath( const std::string& path) const = 0; - virtual Network* FindRememberedNetworkByUniqueId( - const std::string& unique_id) const = 0; // Return a pointer to the ONC dictionary for a network identified by unique // ID. Returns NULL if there is no ONC dictionary available for that network. @@ -1596,10 +1606,6 @@ class NetworkLibrary { // Return true if a profile matching |type| is loaded. virtual bool HasProfileType(NetworkProfileType type) const = 0; - // Move the network to the shared/global profile. - virtual void SetNetworkProfile(const std::string& service_path, - NetworkProfileType type) = 0; - // Returns false if there is no way to connect to this network, even with // user input (e.g. it requires a user profile but none is available). virtual bool CanConnectToNetwork(const Network* network) const = 0; diff --git a/chrome/browser/chromeos/cros/network_library_impl_base.cc b/chrome/browser/chromeos/cros/network_library_impl_base.cc index ace8e0b..7c2427f 100644 --- a/chrome/browser/chromeos/cros/network_library_impl_base.cc +++ b/chrome/browser/chromeos/cros/network_library_impl_base.cc @@ -19,7 +19,6 @@ using content::BrowserThread; namespace chromeos { -// Local constants. namespace { // Only send network change notifications to observers once every 50ms. @@ -28,9 +27,6 @@ const int kNetworkNotifyDelayMs = 50; // How long we should remember that cellular plan payment was received. const int kRecentPlanPaymentHours = 6; -//////////////////////////////////////////////////////////////////////////////// -// Misc. - NetworkProfileType GetProfileTypeForSource(NetworkUIData::ONCSource source) { switch (source) { case NetworkUIData::ONC_SOURCE_DEVICE_POLICY: @@ -67,11 +63,13 @@ NetworkLibraryImplBase::NetworkLibraryImplBase() } NetworkLibraryImplBase::~NetworkLibraryImplBase() { + network_profile_observers_.Clear(); network_manager_observers_.Clear(); data_plan_observers_.Clear(); pin_operation_observers_.Clear(); user_action_observers_.Clear(); - DeleteNetworks(); + STLDeleteValues(&network_map_); + ClearNetworks(); DeleteRememberedNetworks(); STLDeleteValues(&data_plan_map_); STLDeleteValues(&device_map_); @@ -83,6 +81,16 @@ NetworkLibraryImplBase::~NetworkLibraryImplBase() { ////////////////////////////////////////////////////////////////////////////// // NetworkLibrary implementation. +void NetworkLibraryImplBase::AddNetworkProfileObserver( + NetworkProfileObserver* observer) { + network_profile_observers_.AddObserver(observer); +} + +void NetworkLibraryImplBase::RemoveNetworkProfileObserver( + NetworkProfileObserver* observer) { + network_profile_observers_.RemoveObserver(observer); +} + void NetworkLibraryImplBase::AddNetworkManagerObserver( NetworkManagerObserver* observer) { if (!network_manager_observers_.HasObserver(observer)) @@ -579,15 +587,6 @@ Network* NetworkLibraryImplBase::FindRememberedNetworkByPath( return NULL; } -Network* NetworkLibraryImplBase::FindRememberedNetworkByUniqueId( - const std::string& unique_id) const { - NetworkMap::const_iterator found = - remembered_network_unique_id_map_.find(unique_id); - if (found != remembered_network_unique_id_map_.end()) - return found->second; - return NULL; -} - const base::DictionaryValue* NetworkLibraryImplBase::FindOncForNetwork( const std::string& unique_id) const { NetworkOncMap::const_iterator iter = network_onc_map_.find(unique_id); @@ -717,33 +716,6 @@ bool NetworkLibraryImplBase::HasProfileType(NetworkProfileType type) const { return false; } -// Note: currently there is no way to change the profile of a network -// unless it is visible (i.e. in network_map_). We change the profile by -// setting the Profile property of the visible network. -// See chromium-os:15523. -void NetworkLibraryImplBase::SetNetworkProfile( - const std::string& service_path, NetworkProfileType type) { - Network* network = FindNetworkByPath(service_path); - if (!network) { - LOG(WARNING) << "SetNetworkProfile: Network not found: " << service_path; - return; - } - if (network->profile_type() == type) { - LOG(WARNING) << "Remembered Network: " << service_path - << " already in profile: " << type; - return; - } - if (network->RequiresUserProfile() && type == PROFILE_SHARED) { - LOG(WARNING) << "SetNetworkProfile to Shared for non sharable network: " - << service_path; - return; - } - VLOG(1) << "Setting network: " << network->name() - << " to profile type: " << type; - SetProfileType(network, type); - NotifyNetworkManagerChanged(false); -} - NetworkLibraryImplBase::NetworkProfile::NetworkProfile(const std::string& p, NetworkProfileType t) : path(p), @@ -1154,12 +1126,20 @@ bool NetworkLibraryImplBase::LoadOncNetworks(const std::string& onc_blob, NetworkUIData::ONCSource source, bool allow_web_trust_from_policy, std::string* error) { + NetworkProfile* profile = GetProfileForType(GetProfileTypeForSource(source)); + if (profile == NULL) { + DLOG(WARNING) << "Profile for ONC source " << source << " doesn't exist."; + return false; + } + OncNetworkParser parser(onc_blob, passphrase, source); parser.set_allow_web_trust_from_policy(allow_web_trust_from_policy); if (!parser.parse_error().empty()) { if (error) *error = parser.parse_error(); + DLOG(WARNING) << "Parse error when loading from ONC source " << source + << ": " << *error; return false; } @@ -1167,9 +1147,11 @@ bool NetworkLibraryImplBase::LoadOncNetworks(const std::string& onc_blob, // Insert each of the available certs into the certificate DB. if (parser.ParseCertificate(i).get() == NULL && !parser.parse_error().empty()) { - DLOG(WARNING) << "Cannot parse certificate in ONC file"; if (error) *error = parser.parse_error(); + DLOG(WARNING) << "Error during parsing certificate at index " << i + << " from ONC source " << source + << ": " << *error; return false; } } @@ -1183,9 +1165,11 @@ bool NetworkLibraryImplBase::LoadOncNetworks(const std::string& onc_blob, bool marked_for_removal = false; Network* network = parser.ParseNetwork(i, &marked_for_removal); if (!network) { - DLOG(WARNING) << "Cannot parse network in ONC file"; if (error) *error = parser.parse_error(); + DLOG(WARNING) << "Error during parsing network at index " << i + << " from ONC source " << source + << ": " << *error; return false; } @@ -1221,7 +1205,9 @@ bool NetworkLibraryImplBase::LoadOncNetworks(const std::string& onc_blob, // networks that are defined in the ONC blob in |network_ids|. They're later // used to clean out any previously-existing networks that had been configured // through policy but are no longer specified in the updated ONC blob. - std::string profile_path(GetProfilePath(GetProfileTypeForSource(source))); + VLOG(1) << "Loading ONC from source " << source << " with " + << parser.GetNetworkConfigsSize() << " network configs" + << " to profile " << profile->path; std::set<std::string>& network_ids(network_source_map_[source]); network_ids.clear(); for (std::vector<Network*>::iterator iter(networks.begin()); @@ -1248,8 +1234,7 @@ bool NetworkLibraryImplBase::LoadOncNetworks(const std::string& onc_blob, } // Set the appropriate profile for |source|. - if (!profile_path.empty()) - dict.SetString(flimflam::kProfileProperty, profile_path); + dict.SetString(flimflam::kProfileProperty, profile->path); // For Ethernet networks, apply them to the current Ethernet service. if (network->type() == TYPE_ETHERNET) { @@ -1507,22 +1492,8 @@ bool NetworkLibraryImplBase::ValidateAndAddRememberedNetwork(Network* network) { } else { NOTREACHED(); } - // Find service path in profiles. Shill does not set the Profile - // property for remembered networks, only active networks. - for (NetworkProfileList::iterator iter = profile_list_.begin(); - iter != profile_list_.end(); ++iter) { - NetworkProfile& profile = *iter; - if (profile.services.find(network->service_path()) != - profile.services.end()) { - network->set_profile_path(profile.path); - network->set_profile_type(profile.type); - VLOG(1) << "ValidateAndAddRememberedNetwork: " << network->service_path() - << " profile: " << profile.path; - break; - } - } - DCHECK(!network->profile_path().empty()) - << "Service path not in any profile: " << network->service_path(); + + VLOG(1) << "ValidateAndAddRememberedNetwork: " << network->service_path(); return true; } @@ -1616,23 +1587,13 @@ void NetworkLibraryImplBase::ClearNetworks() { virtual_networks_.clear(); } -void NetworkLibraryImplBase::ClearRememberedNetworks() { +void NetworkLibraryImplBase::DeleteRememberedNetworks() { + STLDeleteValues(&remembered_network_map_); remembered_network_map_.clear(); - remembered_network_unique_id_map_.clear(); remembered_wifi_networks_.clear(); remembered_virtual_networks_.clear(); } -void NetworkLibraryImplBase::DeleteNetworks() { - STLDeleteValues(&network_map_); - ClearNetworks(); -} - -void NetworkLibraryImplBase::DeleteRememberedNetworks() { - STLDeleteValues(&remembered_network_map_); - ClearRememberedNetworks(); -} - void NetworkLibraryImplBase::DeleteDevice(const std::string& device_path) { NetworkDeviceMap::iterator found = device_map_.find(device_path); if (found == device_map_.end()) { @@ -1649,8 +1610,9 @@ void NetworkLibraryImplBase::DeleteDevice(const std::string& device_path) { //////////////////////////////////////////////////////////////////////////// -void NetworkLibraryImplBase::AddProfile( - const std::string& profile_path, NetworkProfileType profile_type) { +void NetworkLibraryImplBase::AddProfile(const std::string& profile_path, + NetworkProfileType profile_type) { + VLOG(1) << "Adding profile " << profile_path; profile_list_.push_back(NetworkProfile(profile_path, profile_type)); // Check to see if we connected to any networks before a user profile was // available (i.e. before login), but unchecked the "Share" option (i.e. @@ -1723,6 +1685,12 @@ std::string NetworkLibraryImplBase::GetProfilePath(NetworkProfileType type) { //////////////////////////////////////////////////////////////////////////// // Notifications. +void NetworkLibraryImplBase::NotifyNetworkProfileObservers() { + FOR_EACH_OBSERVER(NetworkProfileObserver, + network_profile_observers_, + OnProfileListChanged()); +} + // We call this any time something in NetworkLibrary changes. // TODO(stevenjb): We should consider breaking this into multiple // notifications, e.g. connection state, devices, services, etc. diff --git a/chrome/browser/chromeos/cros/network_library_impl_base.h b/chrome/browser/chromeos/cros/network_library_impl_base.h index 62e9c67..3afb104 100644 --- a/chrome/browser/chromeos/cros/network_library_impl_base.h +++ b/chrome/browser/chromeos/cros/network_library_impl_base.h @@ -64,6 +64,10 @@ class NetworkLibraryImplBase : public NetworkLibrary { // virtual Init implemented in derived classes. // virtual IsCros implemented in derived classes. + virtual void AddNetworkProfileObserver( + NetworkProfileObserver* observer) OVERRIDE; + virtual void RemoveNetworkProfileObserver( + NetworkProfileObserver* observer) OVERRIDE; virtual void AddNetworkManagerObserver( NetworkManagerObserver* observer) OVERRIDE; virtual void RemoveNetworkManagerObserver( @@ -173,8 +177,6 @@ class NetworkLibraryImplBase : public NetworkLibrary { Network* FindRememberedFromNetwork(const Network* network) const; virtual Network* FindRememberedNetworkByPath( const std::string& path) const OVERRIDE; - virtual Network* FindRememberedNetworkByUniqueId( - const std::string& unique_id) const OVERRIDE; virtual const base::DictionaryValue* FindOncForNetwork( const std::string& unique_id) const OVERRIDE; @@ -201,8 +203,6 @@ class NetworkLibraryImplBase : public NetworkLibrary { // virtual GetWifiAccessPoints implemented in derived classes. virtual bool HasProfileType(NetworkProfileType type) const OVERRIDE; - virtual void SetNetworkProfile(const std::string& service_path, - NetworkProfileType type) OVERRIDE; virtual bool CanConnectToNetwork(const Network* network) const OVERRIDE; // Connect to an existing network. @@ -350,8 +350,6 @@ class NetworkLibraryImplBase : public NetworkLibrary { void DeleteRememberedNetwork(const std::string& service_path); void ClearNetworks(); - void ClearRememberedNetworks(); - void DeleteNetworks(); void DeleteRememberedNetworks(); void DeleteDevice(const std::string& device_path); void DeleteDeviceFromDeviceObserversMap(const std::string& device_path); @@ -365,6 +363,7 @@ class NetworkLibraryImplBase : public NetworkLibrary { std::string GetProfilePath(NetworkProfileType type); // Notifications. + void NotifyNetworkProfileObservers(); void NotifyNetworkManagerChanged(bool force_update); void SignalNetworkManagerObservers(); void NotifyNetworkChanged(const Network* network); @@ -378,6 +377,9 @@ class NetworkLibraryImplBase : public NetworkLibrary { const std::string& GetTpmSlot(); const std::string& GetTpmPin(); + // Network profile observer list. + ObserverList<NetworkProfileObserver> network_profile_observers_; + // Network manager observer list. ObserverList<NetworkManagerObserver> network_manager_observers_; @@ -411,9 +413,6 @@ class NetworkLibraryImplBase : public NetworkLibrary { // A service path based map of all remembered Networks. NetworkMap remembered_network_map_; - // A unique_id based map of all remembered Networks. - NetworkMap remembered_network_unique_id_map_; - // A list of services that we are awaiting updates for. PriorityMap network_update_requests_; diff --git a/chrome/browser/chromeos/cros/network_library_impl_cros.cc b/chrome/browser/chromeos/cros/network_library_impl_cros.cc index 7bb29e8..c475cdd 100644 --- a/chrome/browser/chromeos/cros/network_library_impl_cros.cc +++ b/chrome/browser/chromeos/cros/network_library_impl_cros.cc @@ -129,6 +129,8 @@ void NetworkLibraryImplCros::UpdateNetworkStatus( LOG(WARNING) << "UpdateNetworkStatus: Error updating: " << path << "." << key; } + if (key == flimflam::kProfileProperty) + SetProfileTypeFromPath(network); // If we just connected, this may have been added to remembered list. if (!prev_connected && network->connected()) RequestRememberedNetworksUpdate(); @@ -689,7 +691,6 @@ bool NetworkLibraryImplCros::NetworkManagerStatusChanged( if (!value->GetAsList(&vlist)) return false; UpdateRememberedNetworks(vlist); - RequestRememberedNetworksUpdate(); break; } case PROPERTY_INDEX_SERVICES: { @@ -974,7 +975,9 @@ void NetworkLibraryImplCros::UpdateRememberedNetworks( const ListValue* profiles) { VLOG(1) << "UpdateRememberedNetworks"; // Update the list of profiles. - profile_list_.clear(); + NetworkProfileList old_profile_list; + old_profile_list.swap(profile_list_); + for (ListValue::const_iterator iter = profiles->begin(); iter != profiles->end(); ++iter) { std::string profile_path; @@ -990,6 +993,13 @@ void NetworkLibraryImplCros::UpdateRememberedNetworks( profile_type = PROFILE_USER; AddProfile(profile_path, profile_type); } + bool lists_equal = old_profile_list.size() == profile_list_.size() && + std::equal(profile_list_.begin(), profile_list_.end(), + old_profile_list.begin(), AreProfilePathsEqual); + + RequestRememberedNetworksUpdate(); + if (!lists_equal) + NotifyNetworkProfileObservers(); } void NetworkLibraryImplCros::RequestRememberedNetworksUpdate() { @@ -1054,36 +1064,53 @@ void NetworkLibraryImplCros::UpdateProfile( // Add service to profile list. profile.services.insert(service_path); // Request update for remembered network. + // Shill does not set the Profile property for remembered networks, but only + // for the active networks, so we provide |profile_path| to the callback. CrosRequestNetworkProfileEntryProperties( profile_path, service_path, base::Bind(&NetworkLibraryImplCros::RememberedNetworkServiceUpdate, - weak_ptr_factory_.GetWeakPtr())); + weak_ptr_factory_.GetWeakPtr(), + profile_path)); } } void NetworkLibraryImplCros::RememberedNetworkServiceUpdate( + const std::string& profile_path, const std::string& service_path, const base::DictionaryValue* properties) { - if (!properties) { - // Remembered network no longer exists. - DeleteRememberedNetwork(service_path); + VLOG(2) << "RememberedNetworkServiceUpdate: profile: " << profile_path + << " service: " << service_path + << (properties == NULL ? " got removed" : " got updated"); + if (properties) { + ParseRememberedNetwork(profile_path, service_path, *properties); } else { - ParseRememberedNetwork(service_path, *properties); + // Remove this service from the respective Profile::services list. + for (NetworkProfileList::iterator iter = profile_list_.begin(); + iter != profile_list_.end(); ++iter) { + NetworkProfile& profile = *iter; + if (profile.path != profile_path) + continue; + + if (profile.services.erase(service_path) != 0) { + VLOG(1) << "Removed service path: " << service_path + << " from Profile::services of: " << profile_path; + } + break; + } } } // Returns NULL if |service_path| refers to a network that is not a // remembered type. Called from RememberedNetworkServiceUpdate. Network* NetworkLibraryImplCros::ParseRememberedNetwork( - const std::string& service_path, const DictionaryValue& info) { + const std::string& profile_path, + const std::string& service_path, + const DictionaryValue& info) { Network* remembered; NetworkMap::iterator found = remembered_network_map_.find(service_path); if (found != remembered_network_map_.end()) { remembered = found->second; - // Erase entry from network_unique_id_map_ in case unique id changes. - if (!remembered->unique_id().empty()) - remembered_network_unique_id_map_.erase(remembered->unique_id()); if (remembered->network_parser()) remembered->network_parser()->UpdateNetworkFromInfo(info, remembered); } else { @@ -1100,9 +1127,7 @@ Network* NetworkLibraryImplCros::ParseRememberedNetwork( } } - if (!remembered->unique_id().empty()) - remembered_network_unique_id_map_[remembered->unique_id()] = remembered; - + remembered->set_profile_path(profile_path); SetProfileTypeFromPath(remembered); VLOG(2) << "ParseRememberedNetwork: " << remembered->name() @@ -1337,4 +1362,10 @@ void NetworkLibraryImplCros::SetIPParametersCallback( RefreshIPConfig(network); } +// static +bool NetworkLibraryImplCros::AreProfilePathsEqual(const NetworkProfile& a, + const NetworkProfile& b) { + return a.path == b.path; +} + } // namespace chromeos diff --git a/chrome/browser/chromeos/cros/network_library_impl_cros.h b/chrome/browser/chromeos/cros/network_library_impl_cros.h index 43dab41..8debe51b 100644 --- a/chrome/browser/chromeos/cros/network_library_impl_cros.h +++ b/chrome/browser/chromeos/cros/network_library_impl_cros.h @@ -127,7 +127,8 @@ class NetworkLibraryImplCros : public NetworkLibraryImplBase { void NetworkServiceUpdate(const std::string& service_path, const base::DictionaryValue* properties); - void RememberedNetworkServiceUpdate(const std::string& service_path, + void RememberedNetworkServiceUpdate(const std::string& profile_path, + const std::string& service_path, const base::DictionaryValue* properties); void NetworkDeviceUpdate(const std::string& device_path, const base::DictionaryValue* properties); @@ -167,7 +168,8 @@ class NetworkLibraryImplCros : public NetworkLibraryImplBase { void RequestRememberedNetworksUpdate(); void UpdateProfile(const std::string& profile_path, const base::DictionaryValue* properties); - Network* ParseRememberedNetwork(const std::string& service_path, + Network* ParseRememberedNetwork(const std::string& profile_path, + const std::string& service_path, const base::DictionaryValue& info); // NetworkDevice list management functions. @@ -175,6 +177,10 @@ class NetworkLibraryImplCros : public NetworkLibraryImplBase { void ParseNetworkDevice(const std::string& device_path, const base::DictionaryValue& info); + // Compare two network profiles by their path. + static bool AreProfilePathsEqual(const NetworkProfile& a, + const NetworkProfile& b); + // Empty device observer to ensure that device property updates are received. class NetworkLibraryDeviceObserver : public NetworkDeviceObserver { public: diff --git a/chrome/browser/chromeos/cros/network_library_impl_stub.cc b/chrome/browser/chromeos/cros/network_library_impl_stub.cc index d0bf25e..d6bc7e9 100644 --- a/chrome/browser/chromeos/cros/network_library_impl_stub.cc +++ b/chrome/browser/chromeos/cros/network_library_impl_stub.cc @@ -391,8 +391,8 @@ void NetworkLibraryImplStub::AddStubRememberedNetwork(Network* network) { if (remembered) { remembered->set_name(network->name()); remembered->set_unique_id(network->unique_id()); - // ValidateAndAddRememberedNetwork will insert the network into the matching - // profile and set the profile type + path. + // ValidateAndAddRememberedNetwork will insert the network into the right + // remembered_*_networks_ list and the remembered_network_map_. if (!ValidateAndAddRememberedNetwork(remembered)) NOTREACHED(); } diff --git a/chrome/browser/policy/network_configuration_updater.cc b/chrome/browser/policy/network_configuration_updater.cc index 68439a3..2642e3e 100644 --- a/chrome/browser/policy/network_configuration_updater.cc +++ b/chrome/browser/policy/network_configuration_updater.cc @@ -23,66 +23,74 @@ NetworkConfigurationUpdater::NetworkConfigurationUpdater( : policy_change_registrar_( policy_service, POLICY_DOMAIN_CHROME, std::string()), network_library_(network_library), - allow_web_trust_(false) { + allow_web_trust_(false), + policy_service_(policy_service) { DCHECK(network_library_); policy_change_registrar_.Observe( key::kDeviceOpenNetworkConfiguration, - base::Bind(&NetworkConfigurationUpdater::ApplyNetworkConfiguration, + base::Bind(&NetworkConfigurationUpdater::OnPolicyChanged, base::Unretained(this), - chromeos::NetworkUIData::ONC_SOURCE_DEVICE_POLICY, - &device_network_config_)); + chromeos::NetworkUIData::ONC_SOURCE_DEVICE_POLICY)); policy_change_registrar_.Observe( key::kOpenNetworkConfiguration, - base::Bind(&NetworkConfigurationUpdater::ApplyNetworkConfiguration, + base::Bind(&NetworkConfigurationUpdater::OnPolicyChanged, base::Unretained(this), - chromeos::NetworkUIData::ONC_SOURCE_USER_POLICY, - &user_network_config_)); - - // Apply the current values immediately. - const PolicyMap& policies = policy_service->GetPolicies(POLICY_DOMAIN_CHROME, - std::string()); - ApplyNetworkConfiguration( - chromeos::NetworkUIData::ONC_SOURCE_DEVICE_POLICY, - &device_network_config_, - NULL, - policies.GetValue(key::kDeviceOpenNetworkConfiguration)); - ApplyNetworkConfiguration( - chromeos::NetworkUIData::ONC_SOURCE_USER_POLICY, - &user_network_config_, - NULL, - policies.GetValue(key::kOpenNetworkConfiguration)); + chromeos::NetworkUIData::ONC_SOURCE_USER_POLICY)); + + network_library_->AddNetworkProfileObserver(this); + + // Apply the current policies immediately. + ApplyNetworkConfigurations(); } -NetworkConfigurationUpdater::~NetworkConfigurationUpdater() {} +NetworkConfigurationUpdater::~NetworkConfigurationUpdater() { + network_library_->RemoveNetworkProfileObserver(this); +} -void NetworkConfigurationUpdater::ApplyNetworkConfiguration( +void NetworkConfigurationUpdater::OnProfileListChanged() { + VLOG(1) << "Network profile list changed, applying policies."; + ApplyNetworkConfigurations(); +} + +void NetworkConfigurationUpdater::OnPolicyChanged( chromeos::NetworkUIData::ONCSource onc_source, - std::string* cached_value, const base::Value* previous, const base::Value* current) { + VLOG(1) << "Policy for ONC source " << onc_source << " changed."; + ApplyNetworkConfigurations(); +} + +void NetworkConfigurationUpdater::ApplyNetworkConfigurations() { + ApplyNetworkConfiguration(key::kDeviceOpenNetworkConfiguration, + chromeos::NetworkUIData::ONC_SOURCE_DEVICE_POLICY); + ApplyNetworkConfiguration(key::kOpenNetworkConfiguration, + chromeos::NetworkUIData::ONC_SOURCE_USER_POLICY); +} + +void NetworkConfigurationUpdater::ApplyNetworkConfiguration( + const std::string& policy_key, + chromeos::NetworkUIData::ONCSource onc_source) { + VLOG(1) << "Apply policy for ONC source " << onc_source; + const PolicyMap& policies = policy_service_->GetPolicies(POLICY_DOMAIN_CHROME, + std::string()); + const base::Value* policy_value = policies.GetValue(policy_key); + std::string new_network_config; - if (current != NULL) { + if (policy_value != NULL) { // If the policy is not a string, we issue a warning, but still clear the // network configuration. - if (!current->GetAsString(&new_network_config)) - LOG(WARNING) << "Invalid network configuration."; + if (!policy_value->GetAsString(&new_network_config)) + LOG(WARNING) << "ONC policy is not a string value."; } - // We need to load an empty configuration to get rid of any configuration - // that has been installed previously. An empty string also works, but - // generates warnings and errors, which we'd like to avoid. + // An empty string is not a valid ONC and generates warnings and + // errors. Replace by a valid empty configuration. if (new_network_config.empty()) new_network_config = kEmptyConfiguration; - if (*cached_value != new_network_config) { - *cached_value = new_network_config; - std::string error; - if (!network_library_->LoadOncNetworks(new_network_config, "", onc_source, - allow_web_trust_, &error)) { - LOG(WARNING) << "Network library failed to load ONC configuration:" - << error; - } - } + std::string unused_error; + network_library_->LoadOncNetworks(new_network_config, "", onc_source, + allow_web_trust_, &unused_error); } } // namespace policy diff --git a/chrome/browser/policy/network_configuration_updater.h b/chrome/browser/policy/network_configuration_updater.h index b83818f..9b4ed5b 100644 --- a/chrome/browser/policy/network_configuration_updater.h +++ b/chrome/browser/policy/network_configuration_updater.h @@ -7,6 +7,8 @@ #include <string> +#include "chrome/browser/chromeos/cros/network_constants.h" +#include "chrome/browser/chromeos/cros/network_library.h" #include "chrome/browser/chromeos/cros/network_ui_data.h" #include "chrome/browser/policy/policy_service.h" @@ -14,22 +16,23 @@ namespace base { class Value; } -namespace chromeos { -class NetworkLibrary; -} - namespace policy { class PolicyMap; -// Keeps track of the network configuration policy settings and updates the -// network definitions whenever the configuration changes. -class NetworkConfigurationUpdater { +// Keeps track of the network configuration policy settings and Shill's +// profiles. Requests the NetworkLibrary to apply the ONC of the network +// policies when necessary. +class NetworkConfigurationUpdater + : public chromeos::NetworkLibrary::NetworkProfileObserver { public: NetworkConfigurationUpdater(PolicyService* policy_service, chromeos::NetworkLibrary* network_library); virtual ~NetworkConfigurationUpdater(); + // NetworkProfileObserver overrides. + virtual void OnProfileListChanged() OVERRIDE; + // Web trust isn't given to certificates imported from ONC by default. // Setting |allow_web_trust| to true allows giving Web trust to the // certificates that request it. @@ -39,13 +42,21 @@ class NetworkConfigurationUpdater { static const char kEmptyConfiguration[]; private: - // Extracts ONC string from |policy_map| and pushes the configuration to - // |network_library_| if it's different from |*cached_value| (which is - // updated). - void ApplyNetworkConfiguration(chromeos::NetworkUIData::ONCSource onc_source, - std::string* cached_value, - const base::Value* previous, - const base::Value* current); + // Callback that's called by |policy_service_| if the respective ONC policy + // changed. + void OnPolicyChanged(chromeos::NetworkUIData::ONCSource onc_source, + const base::Value* previous, + const base::Value* current); + + // Retrieves the ONC policies from |policy_service_| and pushes the + // configurations to |network_library_|. Ensures that a device policy is + // always overwritten by a user policy. + void ApplyNetworkConfigurations(); + + // Push the policy stored at |policy_key| for |onc_source| to + // |network_library_|. + void ApplyNetworkConfiguration(const std::string& policy_key, + chromeos::NetworkUIData::ONCSource onc_source); // Wraps the policy service we read network configuration from. PolicyChangeRegistrar policy_change_registrar_; @@ -56,9 +67,8 @@ class NetworkConfigurationUpdater { // Whether Web trust is allowed or not. bool allow_web_trust_; - // Current settings. - std::string device_network_config_; - std::string user_network_config_; + // The policy service storing the ONC policies. + PolicyService* policy_service_; DISALLOW_COPY_AND_ASSIGN(NetworkConfigurationUpdater); }; diff --git a/chrome/browser/policy/network_configuration_updater_unittest.cc b/chrome/browser/policy/network_configuration_updater_unittest.cc index d97e2b8..454d0eb 100644 --- a/chrome/browser/policy/network_configuration_updater_unittest.cc +++ b/chrome/browser/policy/network_configuration_updater_unittest.cc @@ -13,7 +13,9 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using testing::AtLeast; using testing::Mock; +using testing::Ne; using testing::Return; using testing::_; @@ -22,11 +24,9 @@ namespace policy { static const char kFakeONC[] = "{ \"GUID\": \"1234\" }"; class NetworkConfigurationUpdaterTest - : public testing::TestWithParam<const char*> { + : public testing::TestWithParam<const char*>{ protected: virtual void SetUp() OVERRIDE { - EXPECT_CALL(network_library_, LoadOncNetworks(_, "", _, _, _)) - .WillRepeatedly(Return(true)); EXPECT_CALL(provider_, IsInitializationComplete()) .WillRepeatedly(Return(true)); provider_.Init(); @@ -60,60 +60,93 @@ TEST_P(NetworkConfigurationUpdaterTest, InitialUpdate) { Value::CreateStringValue(kFakeONC)); provider_.UpdateChromePolicy(policy); - EXPECT_CALL(network_library_, - LoadOncNetworks(kFakeONC, "", NameToONCSource(GetParam()), - false, _)) - .WillOnce(Return(true)); + EXPECT_CALL(network_library_, AddNetworkProfileObserver(_)); + + // Initially, both policies are applied. + EXPECT_CALL(network_library_, LoadOncNetworks( + kFakeONC, "", NameToONCSource(GetParam()), _, _)); + EXPECT_CALL(network_library_, LoadOncNetworks( + NetworkConfigurationUpdater::kEmptyConfiguration, "", + Ne(NameToONCSource(GetParam())), _, _)); + + EXPECT_CALL(network_library_, RemoveNetworkProfileObserver(_)); - NetworkConfigurationUpdater updater(policy_service_.get(), &network_library_); + { + NetworkConfigurationUpdater updater(policy_service_.get(), + &network_library_); + } Mock::VerifyAndClearExpectations(&network_library_); } TEST_P(NetworkConfigurationUpdaterTest, AllowWebTrust) { - NetworkConfigurationUpdater updater(policy_service_.get(), &network_library_); - updater.set_allow_web_trust(true); + { + EXPECT_CALL(network_library_, AddNetworkProfileObserver(_)); - EXPECT_CALL(network_library_, - LoadOncNetworks(kFakeONC, "", NameToONCSource(GetParam()), - true, _)) - .WillOnce(Return(true)); + // Initially web trust is disabled. + EXPECT_CALL(network_library_, LoadOncNetworks(_, _, _, false, _)) + .Times(AtLeast(0)); + NetworkConfigurationUpdater updater(policy_service_.get(), + &network_library_); + Mock::VerifyAndClearExpectations(&network_library_); - PolicyMap policy; - policy.Set(GetParam(), POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, - Value::CreateStringValue(kFakeONC)); - provider_.UpdateChromePolicy(policy); - Mock::VerifyAndClearExpectations(&network_library_); -} + // Web trust should be forwarded to LoadOncNetworks. + EXPECT_CALL(network_library_, LoadOncNetworks(_, _, _, true, _)) + .Times(AtLeast(0)); -TEST_P(NetworkConfigurationUpdaterTest, PolicyChange) { - NetworkConfigurationUpdater updater(policy_service_.get(), &network_library_); + updater.set_allow_web_trust(true); - // We should update if policy changes. - EXPECT_CALL(network_library_, - LoadOncNetworks(kFakeONC, "", NameToONCSource(GetParam()), - false, _)) - .WillOnce(Return(true)); - PolicyMap policy; - policy.Set(GetParam(), POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, - Value::CreateStringValue(kFakeONC)); - provider_.UpdateChromePolicy(policy); - Mock::VerifyAndClearExpectations(&network_library_); + PolicyMap policy; + policy.Set(GetParam(), POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + Value::CreateStringValue(kFakeONC)); + provider_.UpdateChromePolicy(policy); + Mock::VerifyAndClearExpectations(&network_library_); - // No update if the set the same value again. - EXPECT_CALL(network_library_, - LoadOncNetworks(kFakeONC, "", NameToONCSource(GetParam()), - false, _)) - .Times(0); - provider_.UpdateChromePolicy(policy); + EXPECT_CALL(network_library_, RemoveNetworkProfileObserver(_)); + } Mock::VerifyAndClearExpectations(&network_library_); +} - // Another update is expected if the policy goes away. - EXPECT_CALL(network_library_, - LoadOncNetworks(NetworkConfigurationUpdater::kEmptyConfiguration, - "", NameToONCSource(GetParam()), false, _)) - .WillOnce(Return(true)); - policy.Erase(GetParam()); - provider_.UpdateChromePolicy(policy); +TEST_P(NetworkConfigurationUpdaterTest, PolicyChange) { + { + EXPECT_CALL(network_library_, AddNetworkProfileObserver(_)); + + // Ignore the initial updates. + EXPECT_CALL(network_library_, LoadOncNetworks(_, _, _, _, _)) + .Times(AtLeast(0)); + NetworkConfigurationUpdater updater(policy_service_.get(), + &network_library_); + Mock::VerifyAndClearExpectations(&network_library_); + + // We should update if policy changes. + EXPECT_CALL(network_library_, LoadOncNetworks( + kFakeONC, "", NameToONCSource(GetParam()), _, _)); + + // In the current implementation, we always apply both policies. + EXPECT_CALL(network_library_, LoadOncNetworks( + NetworkConfigurationUpdater::kEmptyConfiguration, "", + Ne(NameToONCSource(GetParam())), _, _)); + + PolicyMap policy; + policy.Set(GetParam(), POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + Value::CreateStringValue(kFakeONC)); + provider_.UpdateChromePolicy(policy); + Mock::VerifyAndClearExpectations(&network_library_); + + // Another update is expected if the policy goes away. In the current + // implementation, we always apply both policies. + EXPECT_CALL(network_library_, LoadOncNetworks( + NetworkConfigurationUpdater::kEmptyConfiguration, "", + chromeos::NetworkUIData::ONC_SOURCE_DEVICE_POLICY, _, _)); + + EXPECT_CALL(network_library_, LoadOncNetworks( + NetworkConfigurationUpdater::kEmptyConfiguration, "", + chromeos::NetworkUIData::ONC_SOURCE_USER_POLICY, _, _)); + + EXPECT_CALL(network_library_, RemoveNetworkProfileObserver(_)); + + policy.Erase(GetParam()); + provider_.UpdateChromePolicy(policy); + } Mock::VerifyAndClearExpectations(&network_library_); } |