shill: make setting a property to its current value a no-op
Before this change, setting the EAP authentication properties
on a WiFiService would cause the connection to be dropped.
The connection would drop even if the new values were the same
as the old.
With this change, the connection is only dropped if the new
values differ from the old.
Overview of changes:
- AccessorInterface: have property setters return a bool (rather
than void). Setters should return true to indicate the value was
changed, and false otherwise.
- PropertyAccessor and derived classes:
- Implement the new AccessorInterface.
- Add tests that we implement the new AccessorInterface.
- Custom property setters (various classes):
- Update existing custom setters to return true if the value was
changed, and false otherwise.
- Add tests that custom setters implement the desired behavior.
- DBusAdaptor
- Change SetProperty to propagate the return value of
PropertyStore's setters, rather than Error::IsSuccess().
- In combination with other changes, this means
DBusAdaptor::SetProperty now returns false if the new value is
the same as the old.
- This also suppresses some spurious change notifications from
IPConfig, Manager, and Profile objects.
- Add tests that DBusAdaptor::SetProperty implements the desired
behavior.
- PropertyStore
- Add a change callback. This optional argument to the ctor is
invoked if a setter or clearer modified its property. This
is so that classes don't have to depend on their RPC adaptors
to inform them of a change. (See changes in Service.)
- Have setters pass through the return value of the Accessor,
rather than returning Error::IsSuccess(). In
combination with other changes, this means that setters
now returns false if the new value is the same as the old.
- Add tests that PropertyStore invokes the change callback
appropriately.
- ClearPropertyNonexistent, SetPropertyNonexistent: no callback
- ClearProperty: callback
- SetProperty: callback if and only if property changed
- Service
- Register OnPropertyChanged with PropertyStore, instead of relying
on a callback from ServiceDBusAdaptor. Two reasons for the change:
1) The RPC adaptors should be as trivial as possible, and
2) We can't test code in the RPC adaptors.
3) If we can't test code in the RPC adaptors, go to 1.
- ServiceDBusAdaptor: remove OnPropertyChange callback in SetProperty.
See Service for the rationale.
- Update existing SetProperty tests (various classes)
We now use values that differ from the current value of the property.
This ensures that the setter returns true.
- WiFiServiceTest: add a case to test that EAP authentication property
changes caused cached credentials to be cleared appropriately. This is
redundant given some of the other tests. But given that this was the
original problem in the bug, it seems worth testing specifically.
- HACKING: add some guidelines for what to do when adding properties.
While there:
- Change some HelpRegister... functions to HelpRegisterConst...
- Update some tests to check error.is_set() before reading
error.name(). This avoids a stray pointer dereference.
- Add SetStringmapsProperty to PropertyStore. This is needed because
PropertyStoreTypedTest now tests setters.
- Remove duplicate kAutoConnectProperty test case in ServiceTest.SetProperty
- Remove unused local in WiFiServiceTest.SetPassphraseRemovedCachedCredentials
- Remove unused method Device::HelpRegisterDerivedStrings
- Remove KeyValueStore from the set of types exercised by
PropertyStoreTypedTest. We only use KeyValueStore for const
properties, and PropertyStoreTypedTest tests setting and
clearing.
- Add PropertyChanges test to EthernetEapServiceTest.
BUG=chromium:233681
TEST=new unit tests
Change-Id: I9bdd89fbe6f19101dfcd5f126f2ba9c81533ff97
Reviewed-on: https://gerrit.chromium.org/gerrit/49733
Commit-Queue: mukesh agrawal <quiche@chromium.org>
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Tested-by: mukesh agrawal <quiche@chromium.org>
diff --git a/wifi_service.cc b/wifi_service.cc
index 7cfee73..4f2ba2e 100644
--- a/wifi_service.cc
+++ b/wifi_service.cc
@@ -215,7 +215,7 @@
return storage_identifier_;
}
-void WiFiService::SetPassphrase(const string &passphrase, Error *error) {
+bool WiFiService::SetPassphrase(const string &passphrase, Error *error) {
if (security_ == flimflam::kSecurityWep) {
ValidateWEPPassphrase(passphrase, error);
} else if (security_ == flimflam::kSecurityPsk ||
@@ -226,13 +226,21 @@
error->Populate(Error::kNotSupported);
}
- if (!error->IsSuccess() || passphrase == passphrase_) {
- return;
+ if (!error->IsSuccess()) {
+ return false;
+ }
+ if (passphrase_ == passphrase) {
+ // After a user logs in, Chrome may reconfigure a Service with the
+ // same credentials as before login. When that occurs, we don't
+ // want to bump the user off the network. Hence, we MUST return
+ // early. (See crbug.com/231456#c17)
+ return false;
}
passphrase_ = passphrase;
ClearCachedCredentials();
UpdateConnectable();
+ return true;
}
// ClearPassphrase is separate from SetPassphrase, because the default
@@ -403,10 +411,19 @@
}
// private methods
+void WiFiService::HelpRegisterConstDerivedString(
+ const string &name,
+ string(WiFiService::*get)(Error *)) {
+ mutable_store()->RegisterDerivedString(
+ name,
+ StringAccessor(
+ new CustomAccessor<WiFiService, string>(this, get, NULL)));
+}
+
void WiFiService::HelpRegisterDerivedString(
const string &name,
- string(WiFiService::*get)(Error *),
- void(WiFiService::*set)(const string&, Error *)) {
+ string(WiFiService::*get)(Error *error),
+ bool(WiFiService::*set)(const string &, Error *)) {
mutable_store()->RegisterDerivedString(
name,
StringAccessor(new CustomAccessor<WiFiService, string>(this, get, set)));
@@ -414,7 +431,7 @@
void WiFiService::HelpRegisterWriteOnlyDerivedString(
const string &name,
- void(WiFiService::*set)(const string &, Error *),
+ bool(WiFiService::*set)(const string &, Error *),
void(WiFiService::*clear)(Error *),
const string *default_value) {
mutable_store()->RegisterDerivedString(