shill: cellular: Pass operator-specific MDN to online payment portal.

BUG=chrome-os-partner:20887
TEST=Tested the following:
1. Build and run unit tests.
2. Run `connectivity show services` to verify that the 'Cellular.OlpUrl'
   property of a LTE cellular service includes a 10-digit MDN.
3. Verify that clicking the 'View account' button on the settings page
   of a connected LTE service launches the online account page of the
   mobile carrier.

Change-Id: If7a9660082b3b33812d3f1a0c0f99e01c17265f6
Reviewed-on: https://gerrit.chromium.org/gerrit/61823
Reviewed-by: Arman Uguray <armansito@chromium.org>
Commit-Queue: Ben Chan <benchan@chromium.org>
Tested-by: Ben Chan <benchan@chromium.org>
diff --git a/cellular_capability_universal.cc b/cellular_capability_universal.cc
index dee846e..4bbbfcc 100644
--- a/cellular_capability_universal.cc
+++ b/cellular_capability_universal.cc
@@ -16,7 +16,6 @@
 #include <vector>
 
 #include "shill/adaptor_interfaces.h"
-#include "shill/cellular_operator_info.h"
 #include "shill/cellular_service.h"
 #include "shill/dbus_properties_proxy_interface.h"
 #include "shill/error.h"
@@ -75,10 +74,15 @@
     20000;
 unsigned int CellularCapabilityUniversal::friendly_service_name_id_ = 0;
 
+namespace {
 
-static const char kPhoneNumber[] = "*99#";
+const char kPhoneNumber[] = "*99#";
 
-static string AccessTechnologyToString(uint32 access_technologies) {
+// This identifier is specified in the cellular_operator_info file.
+const char kVzwIdentifier[] = "vzw";
+const size_t kVzwMdnLength = 10;
+
+string AccessTechnologyToString(uint32 access_technologies) {
   if (access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_LTE)
     return flimflam::kNetworkTechnologyLte;
   if (access_technologies & (MM_MODEM_ACCESS_TECHNOLOGY_EVDO0 |
@@ -105,7 +109,7 @@
   return "";
 }
 
-static string AccessTechnologyToTechnologyFamily(uint32 access_technologies) {
+string AccessTechnologyToTechnologyFamily(uint32 access_technologies) {
   if (access_technologies & (MM_MODEM_ACCESS_TECHNOLOGY_LTE |
                              MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS |
                              MM_MODEM_ACCESS_TECHNOLOGY_HSPA |
@@ -125,6 +129,8 @@
   return "";
 }
 
+}  // namespace
+
 CellularCapabilityUniversal::CellularCapabilityUniversal(
     Cellular *cellular,
     ProxyFactory *proxy_factory,
@@ -632,6 +638,17 @@
   }
 }
 
+string CellularCapabilityUniversal::GetMdnForOLP(
+    const CellularOperatorInfo::CellularOperator &cellular_operator) const {
+  // TODO(benchan): This is ugly. Remove carrier specific code once we move
+  // mobile activation logic to carrier-specifc extensions (crbug.com/260073).
+  if (cellular_operator.identifier() == kVzwIdentifier &&
+      mdn_.length() > kVzwMdnLength) {
+    return mdn_.substr(mdn_.length() - kVzwMdnLength);
+  }
+  return mdn_;
+}
+
 void CellularCapabilityUniversal::ReleaseProxies() {
   SLOG(Cellular, 2) << __func__;
   modem_3gpp_proxy_.reset();
@@ -967,11 +984,20 @@
 }
 
 void CellularCapabilityUniversal::UpdateOLP() {
-  if (!modem_info()->cellular_operator_info())
+  SLOG(Cellular, 2) << __func__;
+
+  const CellularOperatorInfo *cellular_operator_info =
+      modem_info()->cellular_operator_info();
+  if (!cellular_operator_info)
+    return;
+
+  const CellularOperatorInfo::CellularOperator *cellular_operator =
+      cellular_operator_info->GetCellularOperatorByMCCMNC(operator_id_);
+  if (!cellular_operator)
     return;
 
   const CellularService::OLP *result =
-      modem_info()->cellular_operator_info()->GetOLPByMCCMNC(operator_id_);
+      cellular_operator_info->GetOLPByMCCMNC(operator_id_);
   if (!result)
     return;
 
@@ -981,7 +1007,8 @@
   ReplaceSubstringsAfterOffset(&post_data, 0, "${iccid}", sim_identifier_);
   ReplaceSubstringsAfterOffset(&post_data, 0, "${imei}", imei_);
   ReplaceSubstringsAfterOffset(&post_data, 0, "${imsi}", imsi_);
-  ReplaceSubstringsAfterOffset(&post_data, 0, "${mdn}", mdn_);
+  ReplaceSubstringsAfterOffset(&post_data, 0, "${mdn}",
+                               GetMdnForOLP(*cellular_operator));
   ReplaceSubstringsAfterOffset(&post_data, 0, "${min}", min_);
   olp.SetPostData(post_data);
   cellular()->service()->SetOLP(olp);
diff --git a/cellular_capability_universal.h b/cellular_capability_universal.h
index c6c6f68..0dd10ce 100644
--- a/cellular_capability_universal.h
+++ b/cellular_capability_universal.h
@@ -18,6 +18,7 @@
 #include "shill/accessor_interface.h"
 #include "shill/cellular.h"
 #include "shill/cellular_capability.h"
+#include "shill/cellular_operator_info.h"
 #include "shill/mm1_bearer_proxy_interface.h"
 #include "shill/mm1_modem_modem3gpp_proxy_interface.h"
 #include "shill/mm1_modem_proxy_interface.h"
@@ -124,6 +125,11 @@
   // Post-payment activation handlers.
   virtual void UpdatePendingActivationState();
 
+  // Returns the operator-specific form of |mdn_|, which is passed to the online
+  // payment portal of a cellular operator.
+  std::string GetMdnForOLP(
+      const CellularOperatorInfo::CellularOperator &cellular_operator) const;
+
   const std::string &mdn() const { return mdn_; }
   void set_mdn(const std::string &mdn) { mdn_ = mdn; }
 
@@ -197,6 +203,7 @@
               DisconnectWithDeferredCallback);
   FRIEND_TEST(CellularCapabilityUniversalMainTest,
               GetNetworkTechnologyStringOnE362);
+  FRIEND_TEST(CellularCapabilityUniversalMainTest, GetMdnForOLP);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, GetTypeString);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, IsMdnValid);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, IsServiceActivationRequired);
diff --git a/cellular_capability_universal_cdma.cc b/cellular_capability_universal_cdma.cc
index 7b9c7ec..af148bd 100644
--- a/cellular_capability_universal_cdma.cc
+++ b/cellular_capability_universal_cdma.cc
@@ -213,13 +213,21 @@
 }
 
 void CellularCapabilityUniversalCDMA::UpdateOLP() {
-  SLOG(Cellular,2) << __func__;
-  if (!modem_info()->cellular_operator_info())
+  SLOG(Cellular, 2) << __func__;
+
+  const CellularOperatorInfo *cellular_operator_info =
+      modem_info()->cellular_operator_info();
+  if (!cellular_operator_info)
+    return;
+
+  string sid_string = UintToString(sid_);
+  const CellularOperatorInfo::CellularOperator *cellular_operator =
+      cellular_operator_info->GetCellularOperatorBySID(sid_string);
+  if (!cellular_operator)
     return;
 
   const CellularService::OLP *result =
-      modem_info()->cellular_operator_info()->GetOLPBySID(
-          UintToString(sid_));
+      cellular_operator_info->GetOLPBySID(sid_string);
   if (!result)
     return;
 
@@ -227,7 +235,8 @@
   olp.CopyFrom(*result);
   string post_data = olp.GetPostData();
   ReplaceSubstringsAfterOffset(&post_data, 0, "${esn}", esn());
-  ReplaceSubstringsAfterOffset(&post_data, 0, "${mdn}", mdn());
+  ReplaceSubstringsAfterOffset(&post_data, 0, "${mdn}",
+                               GetMdnForOLP(*cellular_operator));
   ReplaceSubstringsAfterOffset(&post_data, 0, "${meid}", meid());
   olp.SetPostData(post_data);
   if (cellular()->service().get())
diff --git a/cellular_capability_universal_cdma_unittest.cc b/cellular_capability_universal_cdma_unittest.cc
index e9e707f..371b09b 100644
--- a/cellular_capability_universal_cdma_unittest.cc
+++ b/cellular_capability_universal_cdma_unittest.cc
@@ -349,26 +349,40 @@
 }
 
 TEST_F(CellularCapabilityUniversalCDMAMainTest, UpdateOLP) {
+  CellularOperatorInfo::CellularOperator cellular_operator;
   CellularService::OLP test_olp;
   test_olp.SetURL("http://testurl");
   test_olp.SetMethod("POST");
   test_olp.SetPostData("esn=${esn}&mdn=${mdn}&meid=${meid}");
 
   capability_->esn_ = "0";
-  capability_->mdn_ = "3";
+  capability_->mdn_ = "10123456789";
   capability_->meid_= "4";
   capability_->sid_ = 1;
 
+  string sid_string = base::StringPrintf("%u", capability_->sid_);
   EXPECT_CALL(*modem_info_.mock_cellular_operator_info(),
-      GetOLPBySID(base::StringPrintf("%u", capability_->sid_)))
+              GetCellularOperatorBySID(sid_string))
+      .WillRepeatedly(Return(&cellular_operator));
+  EXPECT_CALL(*modem_info_.mock_cellular_operator_info(),
+              GetOLPBySID(sid_string))
       .WillRepeatedly(Return(&test_olp));
 
   SetService();
+
+  cellular_operator.identifier_ = "vzw";
+  capability_->UpdateOLP();
+  const CellularService::OLP &vzw_olp = cellular_->service()->olp();
+  EXPECT_EQ("http://testurl", vzw_olp.GetURL());
+  EXPECT_EQ("POST", vzw_olp.GetMethod());
+  EXPECT_EQ("esn=0&mdn=0123456789&meid=4", vzw_olp.GetPostData());
+
+  cellular_operator.identifier_ = "foo";
   capability_->UpdateOLP();
   const CellularService::OLP &olp = cellular_->service()->olp();
   EXPECT_EQ("http://testurl", olp.GetURL());
   EXPECT_EQ("POST", olp.GetMethod());
-  EXPECT_EQ("esn=0&mdn=3&meid=4", olp.GetPostData());
+  EXPECT_EQ("esn=0&mdn=10123456789&meid=4", olp.GetPostData());
 }
 
 TEST_F(CellularCapabilityUniversalCDMAMainTest, ActivateAutomatic) {
diff --git a/cellular_capability_universal_unittest.cc b/cellular_capability_universal_unittest.cc
index 152da83..1d80a86 100644
--- a/cellular_capability_universal_unittest.cc
+++ b/cellular_capability_universal_unittest.cc
@@ -1668,7 +1668,29 @@
             cellular_->service()->storage_identifier_);
 }
 
+TEST_F(CellularCapabilityUniversalMainTest, GetMdnForOLP) {
+  CellularOperatorInfo::CellularOperator cellular_operator;
+
+  cellular_operator.identifier_ = "vzw";
+  capability_->mdn_ = "";
+  EXPECT_EQ("", capability_->GetMdnForOLP(cellular_operator));
+  capability_->mdn_ = "0123456789";
+  EXPECT_EQ("0123456789", capability_->GetMdnForOLP(cellular_operator));
+  capability_->mdn_ = "10123456789";
+  EXPECT_EQ("0123456789", capability_->GetMdnForOLP(cellular_operator));
+
+  cellular_operator.identifier_ = "foo";
+  capability_->mdn_ = "";
+  EXPECT_EQ("", capability_->GetMdnForOLP(cellular_operator));
+  capability_->mdn_ = "0123456789";
+  EXPECT_EQ("0123456789", capability_->GetMdnForOLP(cellular_operator));
+  capability_->mdn_ = "10123456789";
+  EXPECT_EQ("10123456789", capability_->GetMdnForOLP(cellular_operator));
+}
+
 TEST_F(CellularCapabilityUniversalMainTest, UpdateOLP) {
+  CellularOperatorInfo::CellularOperator cellular_operator;
+
   CellularService::OLP test_olp;
   test_olp.SetURL("http://testurl");
   test_olp.SetMethod("POST");
@@ -1677,21 +1699,33 @@
 
   capability_->imei_ = "1";
   capability_->imsi_ = "2";
-  capability_->mdn_ = "3";
+  capability_->mdn_ = "10123456789";
   capability_->min_ = "5";
   capability_->sim_identifier_ = "6";
   capability_->operator_id_ = "123456";
 
   EXPECT_CALL(*modem_info_.mock_cellular_operator_info(),
+      GetCellularOperatorByMCCMNC(capability_->operator_id_))
+      .WillRepeatedly(Return(&cellular_operator));
+  EXPECT_CALL(*modem_info_.mock_cellular_operator_info(),
       GetOLPByMCCMNC(capability_->operator_id_))
       .WillRepeatedly(Return(&test_olp));
 
   SetService();
+  cellular_operator.identifier_ = "vzw";
+  capability_->UpdateOLP();
+  const CellularService::OLP &vzw_olp = cellular_->service()->olp();
+  EXPECT_EQ("http://testurl", vzw_olp.GetURL());
+  EXPECT_EQ("POST", vzw_olp.GetMethod());
+  EXPECT_EQ("imei=1&imsi=2&mdn=0123456789&min=5&iccid=6",
+            vzw_olp.GetPostData());
+
+  cellular_operator.identifier_ = "foo";
   capability_->UpdateOLP();
   const CellularService::OLP &olp = cellular_->service()->olp();
   EXPECT_EQ("http://testurl", olp.GetURL());
   EXPECT_EQ("POST", olp.GetMethod());
-  EXPECT_EQ("imei=1&imsi=2&mdn=3&min=5&iccid=6",
+  EXPECT_EQ("imei=1&imsi=2&mdn=10123456789&min=5&iccid=6",
             olp.GetPostData());
 }
 
diff --git a/cellular_operator_info.h b/cellular_operator_info.h
index e737a2c..300bd97 100644
--- a/cellular_operator_info.h
+++ b/cellular_operator_info.h
@@ -131,11 +131,14 @@
     friend class CellularOperatorInfo;
     friend class CellularOperatorInfoImpl;
     friend class CellularCapabilityUniversalCDMATest;
+    FRIEND_TEST(CellularCapabilityUniversalMainTest, GetMdnForOLP);
+    FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateOLP);
     FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateStorageIdentifier);
     FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
                 CreateFriendlyServiceName);
     FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
                 OnCDMARegistrationChanged);
+    FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, UpdateOLP);
     FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, UpdateOperatorInfo);
 
     std::string country_;