shill: cellular: Simplify CellularService name generation.

Before this CL, the name for cellular service was generated with help from the
cellular capabilities. After this CL, a default initial name is chosen for the
service, which is updated when the network operator has been determined.

BUG=chromium:352237
TEST=- Manual: Check service name shows correctly in UI for different
       operators.
     - Run shill unittests.
     - Run cellular_ServiceName.

Change-Id: I2a25ad076a645a1fe3d85023e2eb9df777ec089e
Reviewed-on: https://chromium-review.googlesource.com/193970
Reviewed-by: Ben Chan <benchan@chromium.org>
Commit-Queue: Prathmesh Prabhu <pprabhu@chromium.org>
Tested-by: Prathmesh Prabhu <pprabhu@chromium.org>
diff --git a/cellular.cc b/cellular.cc
index 0cf1693..bbeb124 100644
--- a/cellular.cc
+++ b/cellular.cc
@@ -14,6 +14,7 @@
 #include <base/bind.h>
 #include <base/callback.h>
 #include <base/files/file_path.h>
+#include <base/strings/string_util.h>
 #include <base/strings/stringprintf.h>
 #include <chromeos/dbus/service_constants.h>
 #include <mobile_provider.h>
@@ -57,7 +58,7 @@
 const char Cellular::kAllowRoaming[] = "AllowRoaming";
 const int64 Cellular::kDefaultScanningTimeoutMilliseconds = 60000;
 const char Cellular::kGenericServiceNamePrefix[] = "MobileNetwork";
-unsigned int Cellular::friendly_service_name_id_ = 0;
+unsigned int Cellular::friendly_service_name_id_ = 1;
 
 Cellular::Operator::Operator() {
   SetName("");
@@ -859,9 +860,15 @@
                                        invalidated_properties);
 }
 
-string Cellular::CreateFriendlyServiceName() {
+string Cellular::CreateDefaultFriendlyServiceName() {
   SLOG(Cellular, 2) << __func__;
-  return capability_.get() ? capability_->CreateFriendlyServiceName() : "";
+  return base::StringPrintf("%s_%u",
+                            kGenericServiceNamePrefix,
+                            friendly_service_name_id_++);
+}
+
+bool Cellular::IsDefaultFriendlyServiceName(const string &service_name) const {
+  return StartsWithASCII(service_name, kGenericServiceNamePrefix, true);
 }
 
 void Cellular::OnModemStateChanged(ModemState new_state) {
@@ -1514,11 +1521,13 @@
     // We could not get a name for the operator, just use the code.
     service_name = "cellular_" + operator_info->mccmnc();
   } else {
-    // TODO(pprabhu) Make the generic prefix more specific based on the type of
-    // device (GSM/CDMA).
-    service_name = base::StringPrintf("%s %u",
-                                      kGenericServiceNamePrefix,
-                                      friendly_service_name_id_++);
+    // We do not have any information, so must fallback to default service name.
+    // Only assign a new default name if the service doesn't already have one,
+    // because we we generate a new name each time.
+    service_name = service()->friendly_name();
+    if (!IsDefaultFriendlyServiceName(service_name)) {
+      service_name = CreateDefaultFriendlyServiceName();
+    }
   }
   service()->SetFriendlyName(service_name);
 }
diff --git a/cellular.h b/cellular.h
index 0c023ff..acef14e 100644
--- a/cellular.h
+++ b/cellular.h
@@ -156,7 +156,9 @@
   static std::string GetStateString(State state);
   static std::string GetModemStateString(ModemState modem_state);
 
-  std::string CreateFriendlyServiceName();
+  std::string CreateDefaultFriendlyServiceName();
+  bool IsDefaultFriendlyServiceName(const std::string &service_name) const;
+
   // Update the home provider from the information in |operator_info|. This
   // information may be from the SIM / received OTA.
   void UpdateHomeProvider(const MobileOperatorInfo *operator_info);
@@ -326,22 +328,18 @@
   friend class CellularServiceTest;
   friend class ModemTest;
   friend class SubscriptionStateOutOfCreditsDetectorTest;
-  FRIEND_TEST(CellularCapabilityCDMATest, CreateFriendlyServiceName);
   FRIEND_TEST(CellularCapabilityCDMATest, GetRegistrationState);
   FRIEND_TEST(CellularCapabilityGSMTest, AllowRoaming);
-  FRIEND_TEST(CellularCapabilityGSMTest, CreateFriendlyServiceName);
   FRIEND_TEST(CellularCapabilityTest, AllowRoaming);
   FRIEND_TEST(CellularCapabilityTest, EnableModemFail);
   FRIEND_TEST(CellularCapabilityTest, EnableModemSucceed);
   FRIEND_TEST(CellularCapabilityTest, FinishEnable);
   FRIEND_TEST(CellularCapabilityTest, GetModemInfo);
   FRIEND_TEST(CellularCapabilityTest, GetModemStatus);
-  FRIEND_TEST(CellularCapabilityUniversalCDMATest, CreateFriendlyServiceName);
   FRIEND_TEST(CellularCapabilityUniversalCDMATest, OnCDMARegistrationChanged);
   FRIEND_TEST(CellularCapabilityUniversalCDMATest, UpdateOLP);
   FRIEND_TEST(CellularCapabilityUniversalCDMATest, UpdateOperatorInfo);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, AllowRoaming);
-  FRIEND_TEST(CellularCapabilityUniversalMainTest, CreateFriendlyServiceName);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, Connect);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, IsServiceActivationRequired);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, SetHomeProvider);
@@ -403,6 +401,7 @@
   FRIEND_TEST(CellularTest, ScanAsynchronousFailure);
   FRIEND_TEST(CellularTest, ScanImmediateFailure);
   FRIEND_TEST(CellularTest, ScanSuccess);
+  FRIEND_TEST(CellularTest, ServiceFriendlyName);
   FRIEND_TEST(CellularTest, SetAllowRoaming);
   FRIEND_TEST(CellularTest, StartModemCallback);
   FRIEND_TEST(CellularTest, StartModemCallbackFail);
diff --git a/cellular_capability.h b/cellular_capability.h
index 05687e7..8fd742f 100644
--- a/cellular_capability.h
+++ b/cellular_capability.h
@@ -182,10 +182,6 @@
   // Invoked by the parent Cellular device when a new service is created.
   virtual void OnServiceCreated() = 0;
 
-  // Returns a user-friendly service name of the network that the modem
-  // currently registers on.
-  virtual std::string CreateFriendlyServiceName() = 0;
-
   // Returns an empty string if the network technology is unknown.
   virtual std::string GetNetworkTechnologyString() const = 0;
 
diff --git a/cellular_capability_cdma.cc b/cellular_capability_cdma.cc
index 4a16f6e..1eba524 100644
--- a/cellular_capability_cdma.cc
+++ b/cellular_capability_cdma.cc
@@ -24,8 +24,6 @@
 namespace shill {
 
 // static
-unsigned int CellularCapabilityCDMA::friendly_service_name_id_ = 0;
-
 const char CellularCapabilityCDMA::kPhoneNumber[] = "#777";
 
 CellularCapabilityCDMA::CellularCapabilityCDMA(Cellular *cellular,
@@ -313,14 +311,6 @@
   proxy_->GetRegistrationState(NULL, callback, kTimeoutDefault);
 }
 
-string CellularCapabilityCDMA::CreateFriendlyServiceName() {
-  SLOG(Cellular, 2) << __func__;
-  if (!cellular()->carrier().empty()) {
-    return cellular()->carrier();
-  }
-  return base::StringPrintf("CDMANetwork%u", friendly_service_name_id_++);
-}
-
 void CellularCapabilityCDMA::UpdateServingOperator() {
   SLOG(Cellular, 2) << __func__;
   if (cellular()->service().get()) {
diff --git a/cellular_capability_cdma.h b/cellular_capability_cdma.h
index 77f3032..4be6442 100644
--- a/cellular_capability_cdma.h
+++ b/cellular_capability_cdma.h
@@ -40,7 +40,6 @@
   virtual bool IsRegistered() const override;
   virtual void SetUnregistered(bool searching) override;
   virtual void OnServiceCreated() override;
-  virtual std::string CreateFriendlyServiceName() override;
   virtual std::string GetNetworkTechnologyString() const override;
   virtual std::string GetRoamingStateString() const override;
   virtual bool AllowRoaming() override;
@@ -69,7 +68,6 @@
   friend class CellularTest;
   FRIEND_TEST(CellularCapabilityCDMATest, Activate);
   FRIEND_TEST(CellularCapabilityCDMATest, ActivateError);
-  FRIEND_TEST(CellularCapabilityCDMATest, CreateFriendlyServiceName);
   FRIEND_TEST(CellularCapabilityCDMATest, GetActivationStateString);
   FRIEND_TEST(CellularCapabilityCDMATest, GetActivationErrorString);
   FRIEND_TEST(CellularServiceTest, IsAutoConnectable);
@@ -117,8 +115,6 @@
   CellularService::OLP olp_;
   std::string usage_url_;
 
-  static unsigned int friendly_service_name_id_;
-
   DISALLOW_COPY_AND_ASSIGN(CellularCapabilityCDMA);
 };
 
diff --git a/cellular_capability_cdma_unittest.cc b/cellular_capability_cdma_unittest.cc
index e2ec268..f99a1ee 100644
--- a/cellular_capability_cdma_unittest.cc
+++ b/cellular_capability_cdma_unittest.cc
@@ -382,13 +382,4 @@
   EXPECT_TRUE(cellular_->service().get());
 }
 
-TEST_F(CellularCapabilityCDMATest, CreateFriendlyServiceName) {
-  CellularCapabilityCDMA::friendly_service_name_id_ = 0;
-  EXPECT_EQ("CDMANetwork0", capability_->CreateFriendlyServiceName());
-  EXPECT_EQ("CDMANetwork1", capability_->CreateFriendlyServiceName());
-  static const char kTestCarrier[] = "A Carrier";
-  cellular_->set_carrier(kTestCarrier);
-  EXPECT_EQ(kTestCarrier, capability_->CreateFriendlyServiceName());
-}
-
 }  // namespace shill
diff --git a/cellular_capability_gsm.cc b/cellular_capability_gsm.cc
index e9d09b2..4291a87 100644
--- a/cellular_capability_gsm.cc
+++ b/cellular_capability_gsm.cc
@@ -29,8 +29,6 @@
 namespace shill {
 
 // static
-unsigned int CellularCapabilityGSM::friendly_service_name_id_ = 0;
-
 const char CellularCapabilityGSM::kNetworkPropertyAccessTechnology[] =
     "access-tech";
 const char CellularCapabilityGSM::kNetworkPropertyID[] = "operator-num";
@@ -432,33 +430,6 @@
   callback.Run(Error());
 }
 
-string CellularCapabilityGSM::CreateFriendlyServiceName() {
-  SLOG(Cellular, 2) << __func__ << ": " << GetRoamingStateString();
-  string name = serving_operator_.GetName();
-  string home_provider_name = cellular()->home_provider().GetName();
-  if (!name.empty()) {
-    // If roaming, try to show "<home-provider> | <serving-operator>", per 3GPP
-    // rules (TS 31.102 and annex A of 122.101).
-    if (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING &&
-        !home_provider_name.empty()) {
-      return home_provider_name + " | " + name;
-    }
-    return name;
-  }
-  if (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME &&
-      !home_provider_name.empty()) {
-    return home_provider_name;
-  }
-  if (!cellular()->carrier().empty()) {
-    return cellular()->carrier();
-  }
-  string serving_operator_code = serving_operator_.GetCode();
-  if (!serving_operator_code.empty()) {
-    return "cellular_" + serving_operator_code;
-  }
-  return base::StringPrintf("GSMNetwork%u", friendly_service_name_id_++);
-}
-
 void CellularCapabilityGSM::SetHomeProvider() {
   string imsi = cellular()->imsi();
   SLOG(Cellular, 2) << __func__ << "(IMSI: " << imsi
diff --git a/cellular_capability_gsm.h b/cellular_capability_gsm.h
index 68b4da9..6e7fc84 100644
--- a/cellular_capability_gsm.h
+++ b/cellular_capability_gsm.h
@@ -50,7 +50,6 @@
   virtual bool IsRegistered() const override;
   virtual void SetUnregistered(bool searching) override;
   virtual void OnServiceCreated() override;
-  virtual std::string CreateFriendlyServiceName() override;
   virtual std::string GetNetworkTechnologyString() const override;
   virtual std::string GetRoamingStateString() const override;
   virtual bool AllowRoaming() override;
@@ -103,7 +102,6 @@
   friend class CellularCapabilityTest;
   FRIEND_TEST(CellularCapabilityGSMTest, AllowRoaming);
   FRIEND_TEST(CellularCapabilityGSMTest, CreateDeviceFromProperties);
-  FRIEND_TEST(CellularCapabilityGSMTest, CreateFriendlyServiceName);
   FRIEND_TEST(CellularCapabilityGSMTest, GetIMEI);
   FRIEND_TEST(CellularCapabilityGSMTest, GetIMSI);
   FRIEND_TEST(CellularCapabilityGSMTest, GetIMSIFails);
@@ -244,8 +242,6 @@
   std::deque<Stringmap> apn_try_list_;
   SimLockStatus sim_lock_status_;
 
-  static unsigned int friendly_service_name_id_;
-
   DISALLOW_COPY_AND_ASSIGN(CellularCapabilityGSM);
 };
 
diff --git a/cellular_capability_gsm_unittest.cc b/cellular_capability_gsm_unittest.cc
index e7c0450..68f2d42 100644
--- a/cellular_capability_gsm_unittest.cc
+++ b/cellular_capability_gsm_unittest.cc
@@ -712,33 +712,6 @@
   EXPECT_EQ(kRoamingStateUnknown, capability_->GetRoamingStateString());
 }
 
-TEST_F(CellularCapabilityGSMTest, CreateFriendlyServiceName) {
-  CellularCapabilityGSM::friendly_service_name_id_ = 0;
-  EXPECT_EQ("GSMNetwork0", capability_->CreateFriendlyServiceName());
-  EXPECT_EQ("GSMNetwork1", capability_->CreateFriendlyServiceName());
-
-  capability_->serving_operator_.SetCode("1234");
-  EXPECT_EQ("cellular_1234", capability_->CreateFriendlyServiceName());
-
-  static const char kTestCarrier[] = "A GSM Carrier";
-  cellular_->set_carrier(kTestCarrier);
-  EXPECT_EQ(kTestCarrier, capability_->CreateFriendlyServiceName());
-
-  static const char kHomeProvider[] = "The GSM Home Provider";
-  cellular_->home_provider_.SetName(kHomeProvider);
-  EXPECT_EQ(kTestCarrier, capability_->CreateFriendlyServiceName());
-  capability_->registration_state_ = MM_MODEM_GSM_NETWORK_REG_STATUS_HOME;
-  EXPECT_EQ(kHomeProvider, capability_->CreateFriendlyServiceName());
-
-  static const char kTestOperator[] = "A GSM Operator";
-  capability_->serving_operator_.SetName(kTestOperator);
-  EXPECT_EQ(kTestOperator, capability_->CreateFriendlyServiceName());
-
-  capability_->registration_state_ = MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING;
-  EXPECT_EQ(StringPrintf("%s | %s", kHomeProvider, kTestOperator),
-            capability_->CreateFriendlyServiceName());
-}
-
 TEST_F(CellularCapabilityGSMTest, SetStorageIdentifier) {
   SetService();
   capability_->OnServiceCreated();
diff --git a/cellular_capability_universal.cc b/cellular_capability_universal.cc
index 999b0a1..a9a7dcf 100644
--- a/cellular_capability_universal.cc
+++ b/cellular_capability_universal.cc
@@ -55,8 +55,6 @@
 const int64
 CellularCapabilityUniversal::kRegistrationDroppedUpdateTimeoutMilliseconds =
     15000;
-const char CellularCapabilityUniversal::kGenericServiceNamePrefix[] =
-    "Mobile Network";
 const char CellularCapabilityUniversal::kRootPath[] = "/";
 const char CellularCapabilityUniversal::kStatusProperty[] = "status";
 const char CellularCapabilityUniversal::kOperatorLongProperty[] =
@@ -71,7 +69,6 @@
 const char CellularCapabilityUniversal::kE362ModelId[] = "E362 WWAN";
 const int CellularCapabilityUniversal::kSetPowerStateTimeoutMilliseconds =
     20000;
-unsigned int CellularCapabilityUniversal::friendly_service_name_id_ = 0;
 
 namespace {
 
@@ -849,43 +846,6 @@
   OnModem3GPPPropertiesChanged(properties, vector<string>());
 }
 
-// static
-string CellularCapabilityUniversal::GenerateNewGenericServiceName() {
-  return base::StringPrintf("%s %u",
-                            kGenericServiceNamePrefix,
-                            friendly_service_name_id_++);
-}
-
-string CellularCapabilityUniversal::CreateFriendlyServiceName() {
-  SLOG(Cellular, 3) << __func__ << ": " << GetRoamingStateString();
-
-  // If |serving_operator_| does not have an operator ID, call
-  // UpdateOperatorInfo() to use |operator_id_| as a fallback when appropriate.
-  if (serving_operator_.GetCode().empty()) {
-    UpdateOperatorInfo();
-  }
-
-  string name = serving_operator_.GetName();
-  string home_provider_name = cellular()->home_provider().GetName();
-  if (!name.empty()) {
-    // If roaming, try to show "<home-provider> | <serving-operator>", per 3GPP
-    // rules (TS 31.102 and annex A of 122.101).
-    if (registration_state_ == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING &&
-        !home_provider_name.empty()) {
-      return home_provider_name + " | " + name;
-    }
-    return name;
-  }
-  if (registration_state_ == MM_MODEM_3GPP_REGISTRATION_STATE_HOME &&
-      !home_provider_name.empty()) {
-    return home_provider_name;
-  }
-  if (!serving_operator_.GetCode().empty()) {
-    return "cellular_" + serving_operator_.GetCode();
-  }
-  return GenerateNewGenericServiceName();
-}
-
 void CellularCapabilityUniversal::SetHomeProvider() {
   const string &imsi = cellular()->imsi();
   SLOG(Cellular, 3) << __func__ << "(IMSI: " << imsi
@@ -936,7 +896,6 @@
                     << oper.GetName() << ", " << oper.GetCountry()
                     << (roaming_required ? ", roaming required" : "");
   InitAPNList();
-  UpdateServiceName();
 }
 
 void CellularCapabilityUniversal::UpdateOLP() {
@@ -977,12 +936,6 @@
   cellular()->service()->SetOLP(olp);
 }
 
-void CellularCapabilityUniversal::UpdateServiceName() {
-  if (cellular()->service()) {
-    cellular()->service()->SetFriendlyName(CreateFriendlyServiceName());
-  }
-}
-
 void CellularCapabilityUniversal::UpdateOperatorInfo() {
   SLOG(Cellular, 3) << __func__;
   // TODO(armansito): Use CellularOperatorInfo here instead of
@@ -1891,9 +1844,6 @@
 
   cellular()->HandleNewRegistrationState();
 
-  // Update the user facing name of the cellular service.
-  UpdateServiceName();
-
   // If the modem registered with the network and the current ICCID is pending
   // activation, then reset the modem.
   UpdatePendingActivationState();
diff --git a/cellular_capability_universal.h b/cellular_capability_universal.h
index 5fb03c8..a82c1a7 100644
--- a/cellular_capability_universal.h
+++ b/cellular_capability_universal.h
@@ -84,7 +84,6 @@
   virtual bool IsRegistered() const override;
   virtual void SetUnregistered(bool searching) override;
   virtual void OnServiceCreated() override;
-  virtual std::string CreateFriendlyServiceName() override;
   virtual std::string GetNetworkTechnologyString() const override;
   virtual std::string GetRoamingStateString() const override;
   virtual bool AllowRoaming() override;
@@ -166,10 +165,6 @@
   static const char kALT3100ModelId[];
   static const char kE362ModelId[];
 
-  // Generic service name prefix, shown when the correct carrier name is
-  // unknown.
-  static const char kGenericServiceNamePrefix[];
-
   static const int64 kActivationRegistrationTimeoutMilliseconds;
   static const int64 kEnterPinTimeoutMilliseconds;
   static const int64 kRegistrationDroppedUpdateTimeoutMilliseconds;
@@ -193,7 +188,6 @@
               ActivationWaitForRegisterTimeout);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, Connect);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, ConnectApns);
-  FRIEND_TEST(CellularCapabilityUniversalMainTest, CreateFriendlyServiceName);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, DisconnectNoProxy);
   FRIEND_TEST(CellularCapabilityUniversalMainTest,
               DisconnectWithDeferredCallback);
@@ -247,7 +241,6 @@
               UpdateRegistrationStateModemNotConnected);
   FRIEND_TEST(CellularCapabilityUniversalMainTest,
               UpdateServiceActivationState);
-  FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateServiceName);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateStorageIdentifier);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateOLP);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateOperatorInfo);
@@ -302,9 +295,6 @@
   void Stop_PowerDownCompleted(const ResultCallback &callback,
                                const Error &error);
 
-  // Updates the name property that is exposed by the service to Chrome.
-  void UpdateServiceName();
-
   // Methods used in acquiring information related to the carrier;
 
   // Updates the Universal operator name and country based on a newly
@@ -419,8 +409,6 @@
   // and removing other non-digit characters.
   std::string NormalizeMdn(const std::string &mdn) const;
 
-  static std::string GenerateNewGenericServiceName();
-
   // Post-payment activation handlers.
   void ResetAfterActivation();
   void UpdateServiceActivationState();
@@ -481,8 +469,6 @@
   base::CancelableClosure registration_dropped_update_callback_;
   int64 registration_dropped_update_timeout_milliseconds_;
 
-  static unsigned int friendly_service_name_id_;
-
   DISALLOW_COPY_AND_ASSIGN(CellularCapabilityUniversal);
 };
 
diff --git a/cellular_capability_universal_cdma.cc b/cellular_capability_universal_cdma.cc
index 37a993e..6959db2 100644
--- a/cellular_capability_universal_cdma.cc
+++ b/cellular_capability_universal_cdma.cc
@@ -39,10 +39,6 @@
 
 }  // namespace
 
-// static
-unsigned int
-CellularCapabilityUniversalCDMA::friendly_service_name_id_cdma_ = 0;
-
 CellularCapabilityUniversalCDMA::CellularCapabilityUniversalCDMA(
     Cellular *cellular,
     ProxyFactory *proxy_factory,
@@ -274,28 +270,6 @@
   OnModemCDMAPropertiesChanged(properties, vector<string>());
 }
 
-string CellularCapabilityUniversalCDMA::CreateFriendlyServiceName() {
-  SLOG(Cellular, 2) << __func__ << ": " << GetRoamingStateString();
-
-  if (provider_.GetCode().empty()) {
-    UpdateOperatorInfo();
-  }
-
-  string name = provider_.GetName();
-  if (!name.empty()) {
-    // TODO(armansito): We may need to show the provider name in a
-    // specific way if roaming.
-    return name;
-  }
-
-  string code = provider_.GetCode();
-  if (!code.empty()) {
-    return "cellular_sid_" + code;
-  }
-
-  return base::StringPrintf("CDMANetwork%u", friendly_service_name_id_cdma_++);
-}
-
 void CellularCapabilityUniversalCDMA::UpdateOperatorInfo() {
   SLOG(Cellular, 2) << __func__;
 
@@ -341,7 +315,6 @@
   SLOG(Cellular, 2) << __func__;
   if (cellular()->service().get()) {
     cellular()->service()->SetServingOperator(cellular()->home_provider());
-    cellular()->service()->SetFriendlyName(CreateFriendlyServiceName());
   }
 }
 
diff --git a/cellular_capability_universal_cdma.h b/cellular_capability_universal_cdma.h
index 3f788c6..c9d2a16 100644
--- a/cellular_capability_universal_cdma.h
+++ b/cellular_capability_universal_cdma.h
@@ -42,7 +42,6 @@
   virtual bool IsRegistered() const override;
   virtual void SetUnregistered(bool searching) override;
   virtual void OnServiceCreated() override;
-  virtual std::string CreateFriendlyServiceName() override;
   virtual std::string GetRoamingStateString() const override;
   virtual void SetupConnectProperties(DBusPropertiesMap *properties) override;
 
@@ -82,8 +81,6 @@
   FRIEND_TEST(CellularCapabilityUniversalCDMADispatcherTest,
               UpdatePendingActivationState);
   FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, ActivateAutomatic);
-  FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
-              CreateFriendlyServiceName);
   FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, IsActivating);
   FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, IsRegistered);
   FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
@@ -144,10 +141,6 @@
   uint32_t nid_;
   uint32_t sid_;
 
-  // TODO(armansito): Use the common name |friendly_service_name_id_| once
-  // CellularCapabilityUniversal gets broken up for 3GPP.
-  static unsigned int friendly_service_name_id_cdma_;
-
   DISALLOW_COPY_AND_ASSIGN(CellularCapabilityUniversalCDMA);
 };
 
diff --git a/cellular_capability_universal_cdma_unittest.cc b/cellular_capability_universal_cdma_unittest.cc
index cf9ddd9..1f324cc 100644
--- a/cellular_capability_universal_cdma_unittest.cc
+++ b/cellular_capability_universal_cdma_unittest.cc
@@ -328,7 +328,6 @@
   EXPECT_EQ("1", cellular_->service()->serving_operator().GetCode());
   EXPECT_EQ("Test", cellular_->service()->serving_operator().GetName());
   EXPECT_EQ("us", cellular_->service()->serving_operator().GetCountry());
-  EXPECT_EQ("Test", cellular_->service()->friendly_name());
 
   capability_->sid_ = 1;
   EXPECT_CALL(*modem_info_.mock_cellular_operator_info(),
@@ -343,31 +342,6 @@
 
 }
 
-TEST_F(CellularCapabilityUniversalCDMAMainTest, CreateFriendlyServiceName) {
-  CellularCapabilityUniversalCDMA::friendly_service_name_id_cdma_ = 0;
-  EXPECT_EQ(0, capability_->sid_);
-  EXPECT_EQ("CDMANetwork0", capability_->CreateFriendlyServiceName());
-  EXPECT_EQ("CDMANetwork1", capability_->CreateFriendlyServiceName());
-
-  capability_->provider_.SetCode("0123");
-  EXPECT_EQ("cellular_sid_0123", capability_->CreateFriendlyServiceName());
-
-  CellularOperatorInfo::CellularOperator *provider =
-      new CellularOperatorInfo::CellularOperator();
-
-  capability_->sid_ = 1;
-  provider->name_list_.push_back(
-      CellularOperatorInfo::LocalizedName("Test", ""));
-  capability_->provider_.SetCode("");
-
-  scoped_ptr<const CellularOperatorInfo::CellularOperator> ptr(provider);
-
-  EXPECT_CALL(*modem_info_.mock_cellular_operator_info(),
-              GetCellularOperatorBySID(_))
-      .WillOnce(Return(ptr.get()));
-  EXPECT_EQ("Test", capability_->CreateFriendlyServiceName());
-}
-
 TEST_F(CellularCapabilityUniversalCDMAMainTest, UpdateOLP) {
   CellularOperatorInfo::CellularOperator cellular_operator;
   CellularService::OLP test_olp;
@@ -615,15 +589,14 @@
 
   const string kPrefix =
       string(shill::kTypeCellular) + "_" + string(kMachineAddress) + "_";
-  const string kDefaultIdentifierPattern = kPrefix + "CDMANetwork*";
 
   // GetCellularOperatorBySID returns NULL.
   EXPECT_CALL(*modem_info_.mock_cellular_operator_info(),
               GetCellularOperatorBySID(_))
       .WillOnce(Return(nullptr));
   capability_->UpdateStorageIdentifier();
-  EXPECT_TRUE(::MatchPattern(cellular_->service()->GetStorageIdentifier(),
-                             kDefaultIdentifierPattern));
+  EXPECT_EQ(kPrefix + cellular_->service()->friendly_name(),
+            cellular_->service()->GetStorageIdentifier());
   Mock::VerifyAndClearExpectations(modem_info_.mock_cellular_operator_info());
 
   CellularOperatorInfo::CellularOperator provider;
@@ -634,8 +607,8 @@
 
   // |provider.identifier_| is empty.
   capability_->UpdateStorageIdentifier();
-  EXPECT_TRUE(::MatchPattern(cellular_->service()->GetStorageIdentifier(),
-                             kDefaultIdentifierPattern));
+  EXPECT_EQ(kPrefix + cellular_->service()->friendly_name(),
+            cellular_->service()->GetStorageIdentifier());
 
   // Success.
   provider.identifier_ = "testidentifier";
diff --git a/cellular_capability_universal_unittest.cc b/cellular_capability_universal_unittest.cc
index 59585c9..dbdf55c 100644
--- a/cellular_capability_universal_unittest.cc
+++ b/cellular_capability_universal_unittest.cc
@@ -937,56 +937,6 @@
                                        vector<string>());
 }
 
-TEST_F(CellularCapabilityUniversalMainTest, UpdateServiceName) {
-  ::DBus::Struct<uint32_t, bool> data;
-  data._1 = 100;
-  data._2 = true;
-  ::DBus::Variant v;
-  ::DBus::MessageIter writer = v.writer();
-  writer << data;
-  EXPECT_CALL(*properties_proxy_, Get(_, MM_MODEM_PROPERTY_SIGNALQUALITY))
-      .WillRepeatedly(Return(v));
-
-  InitProviderDB();
-  capability_->InitProxies();
-
-  SetService();
-
-  size_t len = strlen(CellularCapabilityUniversal::kGenericServiceNamePrefix);
-  EXPECT_EQ(CellularCapabilityUniversal::kGenericServiceNamePrefix,
-            cellular_->service_->friendly_name().substr(0, len));
-
-  cellular_->set_imsi("310240123456789");
-  capability_->SetHomeProvider();
-  EXPECT_EQ("", capability_->spn_);
-  EXPECT_EQ("T-Mobile", cellular_->home_provider().GetName());
-  EXPECT_EQ(CellularCapabilityUniversal::kGenericServiceNamePrefix,
-            cellular_->service_->friendly_name().substr(0, len));
-
-  capability_->registration_state_ = MM_MODEM_3GPP_REGISTRATION_STATE_HOME;
-  capability_->SetHomeProvider();
-  EXPECT_EQ("", capability_->spn_);
-  EXPECT_EQ("T-Mobile", cellular_->home_provider().GetName());
-  EXPECT_EQ("T-Mobile", cellular_->service_->friendly_name());
-
-  capability_->spn_ = "Test Home Provider";
-  capability_->SetHomeProvider();
-  EXPECT_EQ("Test Home Provider", cellular_->home_provider().GetName());
-  EXPECT_EQ("Test Home Provider", cellular_->service_->friendly_name());
-
-  capability_->On3GPPRegistrationChanged(
-      MM_MODEM_3GPP_REGISTRATION_STATE_HOME, "", "OTA Name");
-  EXPECT_EQ("OTA Name", cellular_->service_->friendly_name());
-
-  capability_->On3GPPRegistrationChanged(
-      MM_MODEM_3GPP_REGISTRATION_STATE_HOME, "123", "OTA Name 2");
-  EXPECT_EQ("OTA Name 2", cellular_->service_->friendly_name());
-
-  capability_->On3GPPRegistrationChanged(
-      MM_MODEM_3GPP_REGISTRATION_STATE_HOME, "123", "");
-  EXPECT_EQ("Test Home Provider", cellular_->service_->friendly_name());
-}
-
 TEST_F(CellularCapabilityUniversalMainTest, UpdateRegistrationState) {
   InitProviderDB();
   capability_->InitProxies();
@@ -1626,17 +1576,11 @@
   EXPECT_TRUE(cellular_->service().get());
 
   const string prefix = "cellular_" + string(kMachineAddress) + "_";
-  string default_identifier_pattern =
-      prefix + string(CellularCapabilityUniversal::kGenericServiceNamePrefix);
-  std::replace_if(default_identifier_pattern.begin(),
-                  default_identifier_pattern.end(),
-                  &Service::IllegalChar, '_');
-  default_identifier_pattern += "*";
 
   // |capability_->operator_id_| is "".
   capability_->UpdateStorageIdentifier();
-  EXPECT_TRUE(::MatchPattern(cellular_->service()->storage_identifier_,
-                             default_identifier_pattern));
+  EXPECT_EQ(prefix + cellular_->service()->friendly_name(),
+            cellular_->service()->GetStorageIdentifier());
 
   // GetCellularOperatorByMCCMNC returns NULL.
   capability_->operator_id_ = "1";
@@ -1645,8 +1589,8 @@
       .WillOnce(Return(nullptr));
 
   capability_->UpdateStorageIdentifier();
-  EXPECT_TRUE(::MatchPattern(cellular_->service()->storage_identifier_,
-                             default_identifier_pattern));
+  EXPECT_EQ(prefix + cellular_->service()->friendly_name(),
+            cellular_->service()->GetStorageIdentifier());
   Mock::VerifyAndClearExpectations(modem_info_.mock_cellular_operator_info());
 
   // |cellular_->imsi_| is not ""
@@ -2142,33 +2086,6 @@
   EXPECT_EQ(kOperatorName, cellular_->service()->serving_operator().GetName());
 }
 
-TEST_F(CellularCapabilityUniversalMainTest, CreateFriendlyServiceName) {
-  CellularCapabilityUniversal::friendly_service_name_id_ = 0;
-  EXPECT_EQ("Mobile Network 0", capability_->CreateFriendlyServiceName());
-  EXPECT_EQ("Mobile Network 1", capability_->CreateFriendlyServiceName());
-
-  capability_->operator_id_ = "0123";
-  EXPECT_EQ("cellular_0123", capability_->CreateFriendlyServiceName());
-  EXPECT_EQ("0123", capability_->serving_operator_.GetCode());
-
-  capability_->serving_operator_.SetCode("1234");
-  EXPECT_EQ("cellular_1234", capability_->CreateFriendlyServiceName());
-
-  static const char kHomeProvider[] = "The GSM Home Provider";
-  cellular_->home_provider_.SetName(kHomeProvider);
-  EXPECT_EQ("cellular_1234", capability_->CreateFriendlyServiceName());
-  capability_->registration_state_ = MM_MODEM_3GPP_REGISTRATION_STATE_HOME;
-  EXPECT_EQ(kHomeProvider, capability_->CreateFriendlyServiceName());
-
-  static const char kTestOperator[] = "A GSM Operator";
-  capability_->serving_operator_.SetName(kTestOperator);
-  EXPECT_EQ(kTestOperator, capability_->CreateFriendlyServiceName());
-
-  capability_->registration_state_ = MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING;
-  EXPECT_EQ(StringPrintf("%s | %s", kHomeProvider, kTestOperator),
-            capability_->CreateFriendlyServiceName());
-}
-
 TEST_F(CellularCapabilityUniversalMainTest, IsServiceActivationRequired) {
   capability_->subscription_state_ =
       CellularCapabilityUniversal::kSubscriptionStateProvisioned;
diff --git a/cellular_operator_info.h b/cellular_operator_info.h
index dcb34be..5f2e069 100644
--- a/cellular_operator_info.h
+++ b/cellular_operator_info.h
@@ -133,8 +133,6 @@
     friend class CellularCapabilityUniversalCDMATest;
     friend class MobileOperatorTest;
     FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
-                CreateFriendlyServiceName);
-    FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
                 OnCDMARegistrationChanged);
     FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, UpdateOLP);
     FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, UpdateOperatorInfo);
diff --git a/cellular_service.cc b/cellular_service.cc
index bd2c6b8..380531f 100644
--- a/cellular_service.cc
+++ b/cellular_service.cc
@@ -129,11 +129,9 @@
   store->RegisterString(kCellularPPPUsernameProperty, &ppp_username_);
   store->RegisterWriteOnlyString(kCellularPPPPasswordProperty, &ppp_password_);
 
-  string name = device->CreateFriendlyServiceName();
-  set_friendly_name(name);
+  set_friendly_name(cellular_->CreateDefaultFriendlyServiceName());
   SetStorageIdentifier(string(kTypeCellular) + "_" +
-                       device->address() + "_" + name);
-
+                       cellular_->address() + "_" +  friendly_name());
   // Assume we are not performing any out-of-credits detection.
   // The capability can reinitialize with the appropriate type later.
   InitOutOfCreditsDetection(OutOfCreditsDetector::OOCTypeNone);
diff --git a/cellular_service_unittest.cc b/cellular_service_unittest.cc
index c80ae1e..9aacf76 100644
--- a/cellular_service_unittest.cc
+++ b/cellular_service_unittest.cc
@@ -154,13 +154,6 @@
   service_->SetRoamingState(kRoamingStateHome);
 }
 
-TEST_F(CellularServiceTest, FriendlyName) {
-  static const char kCarrier[] = "Cellular Carrier";
-  device_->set_carrier(kCarrier);
-  service_ = new CellularService(&modem_info_, device_);
-  EXPECT_EQ(kCarrier, GetFriendlyName());
-}
-
 TEST_F(CellularServiceTest, SetStorageIdentifier) {
   EXPECT_EQ(string(kTypeCellular) + "_" +
             kAddress + "_" + GetFriendlyName(),
diff --git a/cellular_unittest.cc b/cellular_unittest.cc
index 191f54d..19c88dd 100644
--- a/cellular_unittest.cc
+++ b/cellular_unittest.cc
@@ -29,6 +29,7 @@
 #include "shill/mock_mm1_modem_modem3gpp_proxy.h"
 #include "shill/mock_mm1_modem_proxy.h"
 #include "shill/mock_mm1_modem_simple_proxy.h"
+#include "shill/mock_mobile_operator_info.h"
 #include "shill/mock_modem_cdma_proxy.h"
 #include "shill/mock_modem_gsm_card_proxy.h"
 #include "shill/mock_modem_gsm_network_proxy.h"
@@ -59,6 +60,7 @@
 using testing::Mock;
 using testing::NiceMock;
 using testing::Return;
+using testing::ReturnRef;
 using testing::SaveArg;
 using testing::SetArgumentPointee;
 using testing::Unused;
@@ -136,6 +138,8 @@
                                         kTestDeviceName)),
         create_gsm_card_proxy_from_factory_(false),
         proxy_factory_(this),
+        mock_home_provider_info_(NULL),
+        mock_serving_operator_info_(NULL),
         device_(new Cellular(&modem_info_,
                              kTestDeviceName,
                              kTestDeviceAddress,
@@ -181,6 +185,16 @@
     mm1_simple_proxy_.reset(new mm1::MockModemSimpleProxy());
   }
 
+  void SetMockMobileOperatorInfoObjects() {
+    mock_home_provider_info_ = new MockMobileOperatorInfo(&dispatcher_);
+    // Takes ownership.
+    device_->set_home_provider_info(mock_home_provider_info_);
+
+    mock_serving_operator_info_ = new MockMobileOperatorInfo(&dispatcher_);
+    // Takes ownership.
+    device_->set_serving_operator_info(mock_serving_operator_info_);
+  }
+
   void InitProviderDB() {
     modem_info_.SetProviderDB(kTestMobileProviderDBPath);
   }
@@ -562,6 +576,8 @@
   scoped_ptr<mm1::MockModemProxy> mm1_proxy_;
   scoped_ptr<mm1::MockModemSimpleProxy> mm1_simple_proxy_;
   TestProxyFactory proxy_factory_;
+  MockMobileOperatorInfo *mock_home_provider_info_;
+  MockMobileOperatorInfo *mock_serving_operator_info_;
   CellularRefPtr device_;
 };
 
@@ -750,6 +766,131 @@
   ASSERT_FALSE(device_->service_->activate_over_non_cellular_network());
 }
 
+TEST_F(CellularTest, ServiceFriendlyName) {
+  SetMockMobileOperatorInfoObjects();
+  CHECK(mock_home_provider_info_);
+  CHECK(mock_serving_operator_info_);
+
+  // Test that the name created for the service is sensible under different
+  // scenarios w.r.t. information about the mobile network operator.
+  const string home_provider_name {"HomeProviderName"};
+  const string serving_operator_name {"ServingOperatorName"};
+  SetCellularType(Cellular::kTypeCDMA);
+
+  // (1) Service created, MNO not known => Default name.
+  EXPECT_CALL(*mock_home_provider_info_, IsMobileNetworkOperatorKnown())
+      .WillOnce(Return(false));
+  EXPECT_CALL(*mock_serving_operator_info_, IsMobileNetworkOperatorKnown())
+      .WillOnce(Return(false));
+  device_->CreateService();
+  // Compare substrings explicitly using EXPECT_EQ for better error message.
+  size_t prefix_len = strlen(Cellular::kGenericServiceNamePrefix);
+  EXPECT_EQ(Cellular::kGenericServiceNamePrefix,
+            device_->service_->friendly_name().substr(0, prefix_len));
+  Mock::VerifyAndClearExpectations(mock_home_provider_info_);
+  Mock::VerifyAndClearExpectations(mock_serving_operator_info_);
+  device_->DestroyService();
+
+  // (2) Service created, then home provider determined => Name provided by
+  //     home provider.
+  mock_home_provider_info_->SetEmptyDefaultsForProperties();
+  EXPECT_CALL(*mock_home_provider_info_, IsMobileNetworkOperatorKnown())
+      .WillOnce(Return(false))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_serving_operator_info_, IsMobileNetworkOperatorKnown())
+      .WillRepeatedly(Return(false));
+  EXPECT_CALL(*mock_home_provider_info_, operator_name())
+      .WillRepeatedly(ReturnRef(home_provider_name));
+  device_->CreateService();
+  // Now emulate an event for updated home provider information.
+  device_->mobile_operator_info_observer_->OnOperatorChanged();
+  EXPECT_EQ(home_provider_name, device_->service_->friendly_name());
+  Mock::VerifyAndClearExpectations(mock_home_provider_info_);
+  Mock::VerifyAndClearExpectations(mock_serving_operator_info_);
+  device_->DestroyService();
+
+  // (3) Service created, then serving operator determined => Name provided by
+  //     serving operator.
+  mock_serving_operator_info_->SetEmptyDefaultsForProperties();
+  EXPECT_CALL(*mock_serving_operator_info_, IsMobileNetworkOperatorKnown())
+      .WillOnce(Return(false))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_home_provider_info_, IsMobileNetworkOperatorKnown())
+      .WillRepeatedly(Return(false));
+  EXPECT_CALL(*mock_serving_operator_info_, operator_name())
+      .WillRepeatedly(ReturnRef(serving_operator_name));
+  device_->CreateService();
+  // Now emulate an event for updated serving operator information.
+  device_->mobile_operator_info_observer_->OnOperatorChanged();
+  EXPECT_EQ(serving_operator_name, device_->service_->friendly_name());
+  Mock::VerifyAndClearExpectations(mock_home_provider_info_);
+  Mock::VerifyAndClearExpectations(mock_serving_operator_info_);
+  device_->DestroyService();
+
+  // (4) Service created, then home provider determined, then serving operator
+  // determined => final name is serving operator.
+  mock_home_provider_info_->SetEmptyDefaultsForProperties();
+  mock_serving_operator_info_->SetEmptyDefaultsForProperties();
+  EXPECT_CALL(*mock_serving_operator_info_, IsMobileNetworkOperatorKnown())
+      .WillOnce(Return(false))
+      .WillOnce(Return(true))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_home_provider_info_, IsMobileNetworkOperatorKnown())
+      .WillOnce(Return(false))
+      .WillOnce(Return(false))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_home_provider_info_, operator_name())
+      .WillRepeatedly(ReturnRef(home_provider_name));
+  EXPECT_CALL(*mock_serving_operator_info_, operator_name())
+      .WillRepeatedly(ReturnRef(serving_operator_name));
+  device_->CreateService();
+  device_->mobile_operator_info_observer_->OnOperatorChanged();
+  device_->mobile_operator_info_observer_->OnOperatorChanged();
+  EXPECT_EQ(serving_operator_name, device_->service_->friendly_name());
+  Mock::VerifyAndClearExpectations(mock_home_provider_info_);
+  Mock::VerifyAndClearExpectations(mock_serving_operator_info_);
+  device_->DestroyService();
+
+  // (5) Service created, then serving operator determined, then home provider
+  // determined => final name is serving operator.
+  mock_home_provider_info_->SetEmptyDefaultsForProperties();
+  mock_serving_operator_info_->SetEmptyDefaultsForProperties();
+  EXPECT_CALL(*mock_serving_operator_info_, IsMobileNetworkOperatorKnown())
+      .WillOnce(Return(false))
+      .WillOnce(Return(false))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_home_provider_info_, IsMobileNetworkOperatorKnown())
+      .WillOnce(Return(false))
+      .WillOnce(Return(true))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_home_provider_info_, operator_name())
+      .WillRepeatedly(ReturnRef(home_provider_name));
+  EXPECT_CALL(*mock_serving_operator_info_, operator_name())
+      .WillRepeatedly(ReturnRef(serving_operator_name));
+  device_->CreateService();
+  device_->mobile_operator_info_observer_->OnOperatorChanged();
+  device_->mobile_operator_info_observer_->OnOperatorChanged();
+  EXPECT_EQ(serving_operator_name, device_->service_->friendly_name());
+  Mock::VerifyAndClearExpectations(mock_home_provider_info_);
+  Mock::VerifyAndClearExpectations(mock_serving_operator_info_);
+  device_->DestroyService();
+
+  // (6) Serving operator known, home provider known, and then service created
+  //     => Name is serving operator.
+  mock_home_provider_info_->SetEmptyDefaultsForProperties();
+  mock_serving_operator_info_->SetEmptyDefaultsForProperties();
+  EXPECT_CALL(*mock_serving_operator_info_, IsMobileNetworkOperatorKnown())
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_home_provider_info_, IsMobileNetworkOperatorKnown())
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_home_provider_info_, operator_name())
+      .WillRepeatedly(ReturnRef(home_provider_name));
+  EXPECT_CALL(*mock_serving_operator_info_, operator_name())
+      .WillRepeatedly(ReturnRef(serving_operator_name));
+  device_->CreateService();
+  EXPECT_EQ(serving_operator_name, device_->service_->friendly_name());
+}
+
 namespace {
 
 MATCHER(ContainsPhoneNumber, "") {
diff --git a/mobile_operator_info.h b/mobile_operator_info.h
index 1ec42c7..dd0d444 100644
--- a/mobile_operator_info.h
+++ b/mobile_operator_info.h
@@ -67,7 +67,7 @@
   // This object does not take ownership of dispatcher, and |dispatcher| is
   // expected to outlive this object.
   explicit MobileOperatorInfo(EventDispatcher *dispatcher);
-  ~MobileOperatorInfo();
+  virtual ~MobileOperatorInfo();
 
   // These functions can be called before Init to read non default database
   // file(s).
@@ -133,7 +133,7 @@
   // values are undefined otherwise.
 
   // Query whether a mobile network operator has been successfully determined.
-  bool IsMobileNetworkOperatorKnown() const;
+  virtual bool IsMobileNetworkOperatorKnown() const;
   // Query whether a mobile network operator has been successfully
   // determined.
   bool IsMobileVirtualNetworkOperatorKnown() const;
@@ -144,9 +144,9 @@
   // access technology agnostic and should be the same across 3GPP and CDMA.
   const std::string &uuid() const;
 
-  const std::string &operator_name() const;
+  virtual const std::string &operator_name() const;
   const std::string &country() const;
-  const std::string &mccmnc() const;
+  virtual const std::string &mccmnc() const;
   const std::string &sid() const;
   const std::string &nid() const;
 
diff --git a/mock_mobile_operator_info.cc b/mock_mobile_operator_info.cc
new file mode 100644
index 0000000..b17a9e2
--- /dev/null
+++ b/mock_mobile_operator_info.cc
@@ -0,0 +1,22 @@
+// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "shill/mock_mobile_operator_info.h"
+
+#include <gmock/gmock.h>
+
+namespace shill {
+
+MockMobileOperatorInfo::MockMobileOperatorInfo(EventDispatcher *dispatcher)
+    : MobileOperatorInfo(dispatcher) {}
+
+MockMobileOperatorInfo::~MockMobileOperatorInfo() {}
+
+void MockMobileOperatorInfo::SetEmptyDefaultsForProperties() {
+  ON_CALL(*this, mccmnc()).WillByDefault(ReturnRef(empty_mccmnc_));
+  ON_CALL(*this, operator_name())
+      .WillByDefault(ReturnRef(empty_operator_name_));
+}
+
+}  // namespace shill
diff --git a/mock_mobile_operator_info.h b/mock_mobile_operator_info.h
new file mode 100644
index 0000000..44c6b60
--- /dev/null
+++ b/mock_mobile_operator_info.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2014 The Chromium OS 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 SHILL_MOCK_MOBILE_OPERATOR_INFO_H_
+#define SHILL_MOCK_MOBILE_OPERATOR_INFO_H_
+
+#include <string>
+
+#include <gmock/gmock.h>
+
+#include "shill/mobile_operator_info.h"
+
+using testing::ReturnRef;
+
+namespace shill {
+
+class MockMobileOperatorInfo : public MobileOperatorInfo {
+ public:
+  explicit MockMobileOperatorInfo(EventDispatcher *dispatcher);
+  virtual ~MockMobileOperatorInfo();
+
+  MOCK_CONST_METHOD0(IsMobileNetworkOperatorKnown, bool());
+
+  MOCK_CONST_METHOD0(mccmnc, const std::string &());
+  MOCK_CONST_METHOD0(operator_name, const std::string &());
+
+  // Sets up the mock object to return empty strings/vectors etc for all
+  // propeties.
+  void SetEmptyDefaultsForProperties();
+
+ private:
+  std::string empty_mccmnc_;
+  std::string empty_operator_name_;
+};
+
+}  // namespace shill
+
+#endif  // SHILL_MOCK_MOBILE_OPERATOR_INFO_H_
diff --git a/shill.gyp b/shill.gyp
index 85c9d5e..458c2de 100644
--- a/shill.gyp
+++ b/shill.gyp
@@ -724,6 +724,7 @@
                 'mock_mm1_modem_simple_proxy.cc',
                 'mock_mm1_modem_time_proxy.cc',
                 'mock_mm1_sim_proxy.cc',
+                'mock_mobile_operator_info.cc',
                 'mock_modem.cc',
                 'mock_modem_cdma_proxy.cc',
                 'mock_modem_gobi_proxy.cc',