shill: WiFiProvider: Emit metrics for remembered WiFi Services

Whenever a profile is loaded, emit an UMA metric indicating how
many WiFi services are now configured by a non-ephemeral profile.
This will allow us to maintain statistics on how many WiFi
services users tend to have at once.

BUG=chromium:396785
TEST=Unit tests + manual: restart shill while logged in, browse to
chrome://histograms and note there are now two (more)
"Network.Shill.RememberedWiFiNetworkCount" metrics -- one when the
default profile was loaded, and one for when the user profile
loaded.

Change-Id: Ia63806106cb88d230e71ce9dde5f81749918b46a
Reviewed-on: https://chromium-review.googlesource.com/209624
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
Commit-Queue: Paul Stewart <pstew@chromium.org>
diff --git a/metrics.cc b/metrics.cc
index 2c50a97..facd006 100644
--- a/metrics.cc
+++ b/metrics.cc
@@ -62,6 +62,12 @@
 const int Metrics::kMetricNetworkSignalStrengthMin = 0;
 const int Metrics::kMetricNetworkSignalStrengthNumBuckets = 40;
 
+const char Metrics::kMetricRememberedWiFiNetworkCount[] =
+    "Network.Shill.WiFi.RememberedNetworkCount";
+const int Metrics::kMetricRememberedWiFiNetworkCountMax = 1024;
+const int Metrics::kMetricRememberedWiFiNetworkCountMin = 0;
+const int Metrics::kMetricRememberedWiFiNetworkCountNumBuckets = 32;
+
 const char Metrics::kMetricTimeOnlineSecondsSuffix[] = "TimeOnline";
 const int Metrics::kMetricTimeOnlineSecondsMax = 8 * 60 * 60;  // 8 hours
 const int Metrics::kMetricTimeOnlineSecondsMin = 1;
diff --git a/metrics.h b/metrics.h
index 21e26c5..3d26442 100644
--- a/metrics.h
+++ b/metrics.h
@@ -357,6 +357,10 @@
   static const int kMetricNetworkSignalStrengthMin;
   static const int kMetricNetworkSignalStrengthMax;
   static const int kMetricNetworkSignalStrengthNumBuckets;
+  static const char kMetricRememberedWiFiNetworkCount[];
+  static const int kMetricRememberedWiFiNetworkCountMin;
+  static const int kMetricRememberedWiFiNetworkCountMax;
+  static const int kMetricRememberedWiFiNetworkCountNumBuckets;
   static const char kMetricTimeOnlineSecondsSuffix[];
   static const int kMetricTimeOnlineSecondsMax;
   static const int kMetricTimeOnlineSecondsMin;
diff --git a/wifi_provider.cc b/wifi_provider.cc
index 6e5381e..ca71ffd 100644
--- a/wifi_provider.cc
+++ b/wifi_provider.cc
@@ -155,6 +155,19 @@
     Error unused_error;
     manager_->RequestScan(Device::kProgressiveScan, kTypeWifi, &unused_error);
   }
+
+  int remembered_network_count = 0;
+  for (const auto &service : services_) {
+    if (service->IsRemembered()) {
+      remembered_network_count++;
+    }
+  }
+  metrics_->SendToUMA(
+      Metrics::kMetricRememberedWiFiNetworkCount,
+      remembered_network_count,
+      Metrics::kMetricRememberedWiFiNetworkCountMin,
+      Metrics::kMetricRememberedWiFiNetworkCountMax,
+      Metrics::kMetricRememberedWiFiNetworkCountNumBuckets);
 }
 
 ServiceRefPtr WiFiProvider::FindSimilarService(
diff --git a/wifi_provider_unittest.cc b/wifi_provider_unittest.cc
index d5d6b58..6ffd97d 100644
--- a/wifi_provider_unittest.cc
+++ b/wifi_provider_unittest.cc
@@ -124,6 +124,12 @@
     return false;
   }
 
+  // Used by mock invocations of RegisterService() to maintain the side-effect
+  // of assigning a profile to |service|.
+  void SetProfileForService(const ServiceRefPtr &service) {
+    service->set_profile(profile_);
+  }
+
  protected:
   typedef scoped_refptr<MockWiFiService> MockWiFiServiceRefPtr;
 
@@ -407,6 +413,12 @@
 TEST_F(WiFiProviderTest, CreateServicesFromProfileWithNoGroups) {
   EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
       .WillOnce(Return(set<string>()));
+  EXPECT_CALL(metrics_, SendToUMA(
+      Metrics::kMetricRememberedWiFiNetworkCount,
+      0,
+      Metrics::kMetricRememberedWiFiNetworkCountMin,
+      Metrics::kMetricRememberedWiFiNetworkCountMax,
+      Metrics::kMetricRememberedWiFiNetworkCountNumBuckets));
   CreateServicesFromProfile();
   EXPECT_TRUE(GetServices().empty());
 }
@@ -419,6 +431,12 @@
       AddServiceToStorage(NULL, kModeManaged, kSecurityNone, false, true));
   EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
       .WillRepeatedly(Return(groups));
+  EXPECT_CALL(metrics_, SendToUMA(
+      Metrics::kMetricRememberedWiFiNetworkCount,
+      0,
+      Metrics::kMetricRememberedWiFiNetworkCountMin,
+      Metrics::kMetricRememberedWiFiNetworkCountMax,
+      Metrics::kMetricRememberedWiFiNetworkCountNumBuckets));
   CreateServicesFromProfile();
   EXPECT_TRUE(GetServices().empty());
 }
@@ -431,6 +449,12 @@
       AddServiceToStorage("", kModeManaged, kSecurityNone, false, true));
   EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
       .WillRepeatedly(Return(groups));
+  EXPECT_CALL(metrics_, SendToUMA(
+      Metrics::kMetricRememberedWiFiNetworkCount,
+      0,
+      Metrics::kMetricRememberedWiFiNetworkCountMin,
+      Metrics::kMetricRememberedWiFiNetworkCountMax,
+      Metrics::kMetricRememberedWiFiNetworkCountNumBuckets));
   CreateServicesFromProfile();
   EXPECT_TRUE(GetServices().empty());
 }
@@ -442,6 +466,12 @@
   groups.insert(AddServiceToStorage("foo", NULL, kSecurityNone, false, true));
   EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
       .WillRepeatedly(Return(groups));
+  EXPECT_CALL(metrics_, SendToUMA(
+      Metrics::kMetricRememberedWiFiNetworkCount,
+      0,
+      Metrics::kMetricRememberedWiFiNetworkCountMin,
+      Metrics::kMetricRememberedWiFiNetworkCountMax,
+      Metrics::kMetricRememberedWiFiNetworkCountNumBuckets));
   CreateServicesFromProfile();
   EXPECT_TRUE(GetServices().empty());
 }
@@ -453,6 +483,12 @@
   groups.insert(AddServiceToStorage("foo", "", kSecurityNone, false, true));
   EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
       .WillRepeatedly(Return(groups));
+  EXPECT_CALL(metrics_, SendToUMA(
+      Metrics::kMetricRememberedWiFiNetworkCount,
+      0,
+      Metrics::kMetricRememberedWiFiNetworkCountMin,
+      Metrics::kMetricRememberedWiFiNetworkCountMax,
+      Metrics::kMetricRememberedWiFiNetworkCountNumBuckets));
   CreateServicesFromProfile();
   EXPECT_TRUE(GetServices().empty());
 }
@@ -464,6 +500,12 @@
   groups.insert(AddServiceToStorage("foo", kModeManaged, NULL, false, true));
   EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
       .WillRepeatedly(Return(groups));
+  EXPECT_CALL(metrics_, SendToUMA(
+      Metrics::kMetricRememberedWiFiNetworkCount,
+      0,
+      Metrics::kMetricRememberedWiFiNetworkCountMin,
+      Metrics::kMetricRememberedWiFiNetworkCountMax,
+      Metrics::kMetricRememberedWiFiNetworkCountNumBuckets));
   CreateServicesFromProfile();
   EXPECT_TRUE(GetServices().empty());
 }
@@ -475,6 +517,12 @@
   groups.insert(AddServiceToStorage("foo", kModeManaged, "", false, true));
   EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
       .WillRepeatedly(Return(groups));
+  EXPECT_CALL(metrics_, SendToUMA(
+      Metrics::kMetricRememberedWiFiNetworkCount,
+      0,
+      Metrics::kMetricRememberedWiFiNetworkCountMin,
+      Metrics::kMetricRememberedWiFiNetworkCountMax,
+      Metrics::kMetricRememberedWiFiNetworkCountNumBuckets));
   CreateServicesFromProfile();
   EXPECT_TRUE(GetServices().empty());
 }
@@ -487,6 +535,12 @@
       AddServiceToStorage("foo", kModeManaged, kSecurityNone, false, false));
   EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
       .WillRepeatedly(Return(groups));
+  EXPECT_CALL(metrics_, SendToUMA(
+      Metrics::kMetricRememberedWiFiNetworkCount,
+      0,
+      Metrics::kMetricRememberedWiFiNetworkCountMin,
+      Metrics::kMetricRememberedWiFiNetworkCountMax,
+      Metrics::kMetricRememberedWiFiNetworkCountNumBuckets));
   CreateServicesFromProfile();
   EXPECT_TRUE(GetServices().empty());
 }
@@ -500,7 +554,15 @@
       kSSID.c_str(), kModeManaged, kSecurityNone, false, true));
   EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
       .WillRepeatedly(Return(groups));
-  EXPECT_CALL(manager_, RegisterService(_)).Times(1);
+  EXPECT_CALL(manager_, RegisterService(_))
+      .WillOnce(Invoke(this, &WiFiProviderTest::SetProfileForService));
+  EXPECT_CALL(manager_, IsServiceEphemeral(_)).WillOnce(Return(false));
+  EXPECT_CALL(metrics_, SendToUMA(
+      Metrics::kMetricRememberedWiFiNetworkCount,
+      1,
+      Metrics::kMetricRememberedWiFiNetworkCountMin,
+      Metrics::kMetricRememberedWiFiNetworkCountMax,
+      Metrics::kMetricRememberedWiFiNetworkCountNumBuckets)).Times(2);
   CreateServicesFromProfile();
   Mock::VerifyAndClearExpectations(&manager_);
   EXPECT_EQ(1, GetServices().size());
@@ -512,6 +574,7 @@
   EXPECT_TRUE(service->IsSecurityMatch(kSecurityNone));
 
   EXPECT_CALL(manager_, RegisterService(_)).Times(0);
+  EXPECT_CALL(manager_, IsServiceEphemeral(_)).WillOnce(Return(false));
   CreateServicesFromProfile();
   EXPECT_EQ(1, GetServices().size());
 }
@@ -525,15 +588,24 @@
       kSSID.c_str(), kModeManaged, kSecurityNone, true, true));
   EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
       .WillRepeatedly(Return(groups));
-  EXPECT_CALL(manager_, RegisterService(_)).Times(1);
+  EXPECT_CALL(manager_, RegisterService(_))
+      .WillOnce(Invoke(this, &WiFiProviderTest::SetProfileForService));
+  EXPECT_CALL(manager_, IsServiceEphemeral(_)).WillOnce(Return(false));
   EXPECT_CALL(manager_, IsTechnologyConnected(Technology::kWifi))
       .WillOnce(Return(true));
   EXPECT_CALL(manager_, RequestScan(_, _, _)).Times(0);
+  EXPECT_CALL(metrics_, SendToUMA(
+      Metrics::kMetricRememberedWiFiNetworkCount,
+      1,
+      Metrics::kMetricRememberedWiFiNetworkCountMin,
+      Metrics::kMetricRememberedWiFiNetworkCountMax,
+      Metrics::kMetricRememberedWiFiNetworkCountNumBuckets)).Times(2);
   CreateServicesFromProfile();
   Mock::VerifyAndClearExpectations(&manager_);
 
   EXPECT_CALL(manager_, RegisterService(_)).Times(0);
   EXPECT_CALL(manager_, IsTechnologyConnected(_)).Times(0);
+  EXPECT_CALL(manager_, IsServiceEphemeral(_)).WillOnce(Return(false));
   CreateServicesFromProfile();
 }
 
@@ -546,17 +618,26 @@
       kSSID.c_str(), kModeManaged, kSecurityNone, true, true));
   EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
       .WillRepeatedly(Return(groups));
-  EXPECT_CALL(manager_, RegisterService(_)).Times(1);
+  EXPECT_CALL(manager_, RegisterService(_))
+      .WillOnce(Invoke(this, &WiFiProviderTest::SetProfileForService));
+  EXPECT_CALL(manager_, IsServiceEphemeral(_)).WillOnce(Return(false));
   EXPECT_CALL(manager_, IsTechnologyConnected(Technology::kWifi))
       .WillOnce(Return(false));
   EXPECT_CALL(manager_, RequestScan(Device::kProgressiveScan,
                                     kTypeWifi, _)).Times(1);
+  EXPECT_CALL(metrics_, SendToUMA(
+      Metrics::kMetricRememberedWiFiNetworkCount,
+      1,
+      Metrics::kMetricRememberedWiFiNetworkCountMin,
+      Metrics::kMetricRememberedWiFiNetworkCountMax,
+      Metrics::kMetricRememberedWiFiNetworkCountNumBuckets)).Times(2);
   CreateServicesFromProfile();
   Mock::VerifyAndClearExpectations(&manager_);
 
   EXPECT_CALL(manager_, RegisterService(_)).Times(0);
   EXPECT_CALL(manager_, IsTechnologyConnected(_)).Times(0);
   EXPECT_CALL(manager_, RequestScan(_, _, _)).Times(0);
+  EXPECT_CALL(manager_, IsServiceEphemeral(_)).WillOnce(Return(false));
   CreateServicesFromProfile();
 }
 
@@ -570,10 +651,19 @@
       AddServiceToStorage("bar", kModeManaged, kSecurityNone, true, true));
   EXPECT_CALL(storage_, GetGroupsWithProperties(TypeWiFiPropertyMatch()))
       .WillRepeatedly(Return(groups));
-  EXPECT_CALL(manager_, RegisterService(_)).Times(2);
+  EXPECT_CALL(manager_, RegisterService(_))
+      .Times(2)
+      .WillRepeatedly(Invoke(this, &WiFiProviderTest::SetProfileForService));
+  EXPECT_CALL(manager_, IsServiceEphemeral(_)).WillRepeatedly(Return(false));
   EXPECT_CALL(manager_, IsTechnologyConnected(Technology::kWifi))
       .WillOnce(Return(true));
   EXPECT_CALL(manager_, RequestScan(_, kTypeWifi, _)).Times(0);
+  EXPECT_CALL(metrics_, SendToUMA(
+      Metrics::kMetricRememberedWiFiNetworkCount,
+      2,
+      Metrics::kMetricRememberedWiFiNetworkCountMin,
+      Metrics::kMetricRememberedWiFiNetworkCountMax,
+      Metrics::kMetricRememberedWiFiNetworkCountNumBuckets));
   CreateServicesFromProfile();
   Mock::VerifyAndClearExpectations(&manager_);