shill: cellular: Update online portal from M[V]NO information.

This CL refactors the code-paths that set the online portal property of cellular
service. In particular, it
 (1) Removes |CellularService::OLP| class, as it is no longer used extensively.
     This class is moved to |CellularOperatorInfo| so that it can still be used
     by the remaining code that uses |CellularOperatorInfo|, and will go away
     completely in a follow up CL.
 (2) Adds |OnOperatorChanged| to the |CellularCapability*| hierarchy as a hook
     to trigger updates whenever network operator information changes.
 (3) Adds |UpdateServiceOLP| to the |CellularCapability*| hierarchy to be called
     from |OnOperatorChanged|. This consolidates the code paths that update the
     OLP property of |CellularService|.
 (4) Updates |CellularCapabilityUniversal| and |CellularCapabilityUniversalCDMA|
     to use the information from MobileOperatorInfo objects to modify the OLP.
 (5) Updates |CellularCapabilityCDMA| to use the hooks in (2) and (3) to update
     the OLP.

BUG=chromium:352243
TEST=Run shill unit-tests.
     Test activation flow on e362, gobi3k GSM/CDMA.
CQ-DEPEND=CL:198597
Change-Id: I10e16144165aafcfc564e1e68a80cce08635163e
Reviewed-on: https://chromium-review.googlesource.com/197770
Reviewed-by: Thieu Le <thieule@chromium.org>
Tested-by: Prathmesh Prabhu <pprabhu@chromium.org>
Commit-Queue: Prathmesh Prabhu <pprabhu@chromium.org>
diff --git a/cellular.cc b/cellular.cc
index 4182d9d..cac0f54 100644
--- a/cellular.cc
+++ b/cellular.cc
@@ -143,13 +143,16 @@
       is_ppp_authenticating_(false),
       scanning_timeout_milliseconds_(kDefaultScanningTimeoutMilliseconds) {
   RegisterProperties();
+  InitCapability(type);
+
   // TODO(pprabhu) Split MobileOperatorInfo into a context that stores the
   // costly database, and lighter objects that |Cellular| can own.
+  // crbug.com/363874
   home_provider_info_->Init();
   serving_operator_info_->Init();
   home_provider_info()->AddObserver(mobile_operator_info_observer_.get());
   serving_operator_info()->AddObserver(mobile_operator_info_observer_.get());
-  InitCapability(type);
+
   SLOG(Cellular, 2) << "Cellular device " << this->link_name()
                     << " initialized.";
 }
@@ -167,6 +170,9 @@
   home_provider_info()->RemoveObserver(mobile_operator_info_observer_.get());
   serving_operator_info()->RemoveObserver(
       mobile_operator_info_observer_.get());
+  // Explicitly delete the observer to ensure that it is destroyed before the
+  // handle to |capability_| that it holds.
+  mobile_operator_info_observer_.reset();
 }
 
 bool Cellular::Load(StoreInterface *storage) {
@@ -380,6 +386,7 @@
       break;
     default: NOTREACHED();
   }
+  mobile_operator_info_observer_->set_capability(capability_.get());
 }
 
 void Cellular::Activate(const string &carrier,
@@ -1578,13 +1585,21 @@
 // MobileOperatorInfoObserver implementation.
 Cellular::MobileOperatorInfoObserver::MobileOperatorInfoObserver(
     Cellular *cellular)
-  : cellular_(cellular) {}
+  : cellular_(cellular),
+    capability_(NULL) {}
 
 Cellular::MobileOperatorInfoObserver::~MobileOperatorInfoObserver() {}
 
 void Cellular::MobileOperatorInfoObserver::OnOperatorChanged() {
   SLOG(Cellular, 3) << __func__;
 
+  // Give the capabilities a chance to hook in and update their state.
+  // Some tests set |capability_| to NULL avoid having to expect the full
+  // behaviour caused by this call.
+  if (capability_) {
+    capability_->OnOperatorChanged();
+  }
+
   const MobileOperatorInfo *home_provider_info =
       cellular_->home_provider_info();
   const MobileOperatorInfo *serving_operator_info =
diff --git a/cellular.h b/cellular.h
index 7dc5206..690118a 100644
--- a/cellular.h
+++ b/cellular.h
@@ -424,10 +424,18 @@
     // is enforced because |cellular| owns this object.
     MobileOperatorInfoObserver(Cellular *cellular);
     virtual ~MobileOperatorInfoObserver();
+
+    void set_capability(CellularCapability *capability) {
+      capability_ = capability;
+    }
+
+    // Inherited from MobileOperatorInfo::Observer
     virtual void OnOperatorChanged() override;
 
    private:
     Cellular *const cellular_;
+    // Owned by |Cellular|.
+    CellularCapability *capability_;
 
     DISALLOW_COPY_AND_ASSIGN(MobileOperatorInfoObserver);
   };
diff --git a/cellular_capability.cc b/cellular_capability.cc
index 522f6b2..71c9d38 100644
--- a/cellular_capability.cc
+++ b/cellular_capability.cc
@@ -123,4 +123,15 @@
   return false;
 }
 
+void CellularCapability::OnOperatorChanged() {
+  SLOG(Cellular, 3) << __func__;
+  if (cellular()->service()) {
+    UpdateServiceOLP();
+  }
+}
+
+void CellularCapability::UpdateServiceOLP() {
+  SLOG(Cellular, 3) << __func__;
+}
+
 }  // namespace shill
diff --git a/cellular_capability.h b/cellular_capability.h
index 8fd742f..fa84f64 100644
--- a/cellular_capability.h
+++ b/cellular_capability.h
@@ -182,6 +182,13 @@
   // Invoked by the parent Cellular device when a new service is created.
   virtual void OnServiceCreated() = 0;
 
+  // Hook called by the Cellular device when either the Home Provider or the
+  // Serving Operator changes. Default implementation calls other hooks declared
+  // below. Overrides should chain up to this function.
+  // Note: This may be called before |CellularService| is created.
+  virtual void OnOperatorChanged();
+  virtual void UpdateServiceOLP();
+
   // 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 1eba524..74e273b 100644
--- a/cellular_capability_cdma.cc
+++ b/cellular_capability_cdma.cc
@@ -95,7 +95,6 @@
 
 void CellularCapabilityCDMA::OnServiceCreated() {
   SLOG(Cellular, 2) << __func__;
-  cellular()->service()->SetOLP(olp_);
   cellular()->service()->SetUsageURL(usage_url_);
   UpdateServingOperator();
   HandleNewActivationState(MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR);
@@ -110,26 +109,36 @@
     cellular()->set_home_provider(oper);
   }
 
-  uint16 prl_version;
   DBusProperties::GetUint32(
       properties, "activation_state", &activation_state_);
-  UpdateOnlinePortal(properties);
-  if (DBusProperties::GetUint16(properties, "prl_version", &prl_version))
-    cellular()->set_prl_version(prl_version);
   // TODO(petkov): For now, get the payment and usage URLs from ModemManager to
   // match flimflam. In the future, get these from an alternative source (e.g.,
   // database, carrier-specific properties, etc.).
-  string payment;
-  if (DBusProperties::GetString(properties, "payment_url", &payment)) {
-    olp_.SetURL(payment);
+  UpdateOnlinePortal(properties);
+  uint16 prl_version;
+  if (DBusProperties::GetUint16(properties, "prl_version", &prl_version))
+    cellular()->set_prl_version(prl_version);
+}
+
+void CellularCapabilityCDMA::UpdateServiceOLP() {
+  SLOG(Cellular, 3) << __func__;
+  // All OLP changes are routed up to the Home Provider.
+  if (!cellular()->home_provider_info()->IsMobileNetworkOperatorKnown()) {
+    return;
   }
-  if (DBusProperties::GetString(properties, "payment_url_method", &payment)) {
-    olp_.SetMethod(payment);
+
+  const vector<MobileOperatorInfo::OnlinePortal> &olp_list =
+      cellular()->home_provider_info()->olp_list();
+  if (olp_list.empty()) {
+    return;
   }
-  if (DBusProperties::GetString(properties, "payment_url_postdata", &payment)) {
-    olp_.SetPostData(payment);
+
+  if (olp_list.size() > 1) {
+    SLOG(Cellular, 1) << "Found multiple online portals. Choosing the first.";
   }
-  DBusProperties::GetString(properties, "usage_url", &usage_url_);
+  cellular()->service()->SetOLP(olp_list[0].url,
+                                olp_list[0].method,
+                                olp_list[0].post_data);
 }
 
 void CellularCapabilityCDMA::SetupConnectProperties(
@@ -360,22 +369,6 @@
   if (DBusProperties::GetString(status_changes, "min", &prop_value))
     cellular()->set_min(prop_value);
 
-  string payment;
-  if (DBusProperties::GetString(status_changes, "payment_url", &payment)) {
-    olp_.SetURL(payment);
-  }
-  if (DBusProperties::GetString(
-          status_changes, "payment_url_method", &payment)) {
-    olp_.SetMethod(payment);
-  }
-  if (DBusProperties::GetString(
-          status_changes, "payment_url_postdata", &payment)) {
-    olp_.SetPostData(payment);
-  }
-  if (cellular()->service().get()) {
-    cellular()->service()->SetOLP(olp_);
-  }
-
   UpdateOnlinePortal(status_changes);
   activation_state_ = activation_state;
   HandleNewActivationState(activation_error);
@@ -404,7 +397,7 @@
       DBusProperties::GetString(properties,
                                 "payment_url_postdata",
                                 &olp_post_data)) {
-    cellular()->serving_operator_info()->UpdateOnlinePortal(olp_url,
+    cellular()->home_provider_info()->UpdateOnlinePortal(olp_url,
                                                             olp_method,
                                                             olp_post_data);
   }
diff --git a/cellular_capability_cdma.h b/cellular_capability_cdma.h
index 4be6442..916248d 100644
--- a/cellular_capability_cdma.h
+++ b/cellular_capability_cdma.h
@@ -105,6 +105,7 @@
 
   // Helper method to extract the online portal information from properties.
   void UpdateOnlinePortal(const DBusPropertiesMap &properties);
+  virtual void UpdateServiceOLP() override;
 
   bool activation_starting_;
   ResultCallback pending_activation_callback_;
@@ -112,7 +113,6 @@
   uint32 activation_state_;
   uint32 registration_state_evdo_;
   uint32 registration_state_1x_;
-  CellularService::OLP olp_;
   std::string usage_url_;
 
   DISALLOW_COPY_AND_ASSIGN(CellularCapabilityCDMA);
diff --git a/cellular_capability_universal.cc b/cellular_capability_universal.cc
index 6caa172..e45d1f0 100644
--- a/cellular_capability_universal.cc
+++ b/cellular_capability_universal.cc
@@ -622,11 +622,16 @@
 }
 
 string CellularCapabilityUniversal::GetMdnForOLP(
-    const CellularOperatorInfo::CellularOperator &cellular_operator) const {
+    const MobileOperatorInfo *operator_info) const {
   // TODO(benchan): This is ugly. Remove carrier specific code once we move
   // mobile activation logic to carrier-specifc extensions (crbug.com/260073).
   const string &mdn = cellular()->mdn();
-  if (cellular_operator.identifier() == kVzwIdentifier) {
+  if (!operator_info->IsMobileNetworkOperatorKnown()) {
+    // Can't make any carrier specific modifications.
+    return mdn;
+  }
+
+  if (operator_info->uuid() == kVzwIdentifier) {
     // subscription_state_ is the definitive indicator of whether we need
     // activation. The OLP expects an all zero MDN in that case.
     if (subscription_state_ == kSubscriptionStateUnprovisioned || mdn.empty()) {
@@ -689,7 +694,6 @@
 void CellularCapabilityUniversal::OnServiceCreated() {
   UpdateServiceActivationState();
   UpdateServingOperator();
-  UpdateOLP();
 
   // WORKAROUND:
   // E362 modems on Verizon network does not properly redirect when a SIM
@@ -871,42 +875,37 @@
   InitAPNList();
 }
 
-void CellularCapabilityUniversal::UpdateOLP() {
+void CellularCapabilityUniversal::UpdateServiceOLP() {
   SLOG(Cellular, 3) << __func__;
 
-  // TODO(armansito): Do this mapping in MobileOperator (See crbug.com/298408).
-  const CellularOperatorInfo *cellular_operator_info =
-      modem_info()->cellular_operator_info();
-  if (!cellular_operator_info)
+  // OLP is based off of the Home Provider.
+  if (!cellular()->home_provider_info()->IsMobileNetworkOperatorKnown()) {
     return;
+  }
 
-  const CellularOperatorInfo::CellularOperator *cellular_operator =
-      cellular_operator_info->GetCellularOperatorByMCCMNC(operator_id_);
-  if (!cellular_operator)
+  const vector<MobileOperatorInfo::OnlinePortal> &olp_list =
+      cellular()->home_provider_info()->olp_list();
+  if (olp_list.empty()) {
     return;
+  }
 
-  const CellularService::OLP *result =
-      cellular_operator_info->GetOLPByMCCMNC(operator_id_);
-  if (!result)
-    return;
-
-  CellularService::OLP olp;
-  olp.CopyFrom(*result);
-  string post_data = olp.GetPostData();
+  if (olp_list.size() > 1) {
+    SLOG(Cellular, 1) << "Found multiple online portals. Choosing the first.";
+  }
+  string post_data = olp_list[0].post_data;
   ReplaceSubstringsAfterOffset(&post_data, 0, "${iccid}",
                                cellular()->sim_identifier());
   ReplaceSubstringsAfterOffset(&post_data, 0, "${imei}", cellular()->imei());
   ReplaceSubstringsAfterOffset(&post_data, 0, "${imsi}", cellular()->imsi());
   ReplaceSubstringsAfterOffset(&post_data, 0, "${mdn}",
-                               GetMdnForOLP(*cellular_operator));
+                               GetMdnForOLP(cellular()->home_provider_info()));
   ReplaceSubstringsAfterOffset(&post_data, 0, "${min}", cellular()->min());
 
   // TODO(armansito): Define constants for the OEM IDs in MobileOperator
   // (See crbug.com/298408).
   string oem_id = (cellular()->model_id() == kE362ModelId) ? "GOG3" : "QUA";
   ReplaceSubstringsAfterOffset(&post_data, 0, "${oem}", oem_id);
-  olp.SetPostData(post_data);
-  cellular()->service()->SetOLP(olp);
+  cellular()->service()->SetOLP(olp_list[0].url, olp_list[0].method, post_data);
 }
 
 void CellularCapabilityUniversal::UpdateOperatorInfo() {
@@ -1063,7 +1062,7 @@
   if (!modem_info()->cellular_operator_info())
     return false;
 
-  const CellularService::OLP *olp =
+  const CellularOperatorInfo::OLP *olp =
       modem_info()->cellular_operator_info()->GetOLPByMCCMNC(operator_id_);
   if (!olp)
     return false;
diff --git a/cellular_capability_universal.h b/cellular_capability_universal.h
index 513b223..85da29b 100644
--- a/cellular_capability_universal.h
+++ b/cellular_capability_universal.h
@@ -125,15 +125,14 @@
 
   // Updates the online payment portal information, if any, for the cellular
   // provider.
-  virtual void UpdateOLP();
+  virtual void UpdateServiceOLP() override;
 
   // 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;
+  std::string GetMdnForOLP(const MobileOperatorInfo *operator_info) const;
 
  private:
   struct ModemModes {
@@ -177,7 +176,6 @@
   friend class CellularCapabilityUniversalTest;
   friend class CellularCapabilityUniversalCDMATest;
   FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, PropertiesChanged);
-  FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, UpdateOLP);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, AllowRoaming);
   FRIEND_TEST(CellularCapabilityUniversalMainTest,
               ActivationWaitForRegisterTimeout);
@@ -236,7 +234,7 @@
               UpdateRegistrationStateModemNotConnected);
   FRIEND_TEST(CellularCapabilityUniversalMainTest,
               UpdateServiceActivationState);
-  FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateOLP);
+  FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateServiceOLP);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateOperatorInfo);
   FRIEND_TEST(CellularCapabilityUniversalMainTest,
               UpdateOperatorInfoViaOperatorId);
diff --git a/cellular_capability_universal_cdma.cc b/cellular_capability_universal_cdma.cc
index 09f7967..43af14a 100644
--- a/cellular_capability_universal_cdma.cc
+++ b/cellular_capability_universal_cdma.cc
@@ -169,7 +169,7 @@
   if (!modem_info()->cellular_operator_info())
     return false;
 
-  const CellularService::OLP *olp =
+  const CellularOperatorInfo::OLP *olp =
       modem_info()->cellular_operator_info()->GetOLPBySID(UintToString(sid_));
   if (!olp)
     return false;
@@ -190,7 +190,6 @@
   UpdateServingOperator();
   HandleNewActivationStatus(MM_CDMA_ACTIVATION_ERROR_NONE);
   UpdatePendingActivationState();
-  UpdateOLP();
 }
 
 void CellularCapabilityUniversalCDMA::UpdateServiceActivationStateProperty() {
@@ -206,36 +205,32 @@
   cellular()->service()->SetActivationState(activation_state);
 }
 
-void CellularCapabilityUniversalCDMA::UpdateOLP() {
+void CellularCapabilityUniversalCDMA::UpdateServiceOLP() {
   SLOG(Cellular, 2) << __func__;
 
-  const CellularOperatorInfo *cellular_operator_info =
-      modem_info()->cellular_operator_info();
-  if (!cellular_operator_info)
+  // In this case, the Home Provider is trivial. All information comes from the
+  // Serving Operator.
+  if (!cellular()->serving_operator_info()->IsMobileNetworkOperatorKnown()) {
     return;
+  }
 
-  string sid_string = UintToString(sid_);
-  const CellularOperatorInfo::CellularOperator *cellular_operator =
-      cellular_operator_info->GetCellularOperatorBySID(sid_string);
-  if (!cellular_operator)
+  const vector<MobileOperatorInfo::OnlinePortal> &olp_list =
+      cellular()->serving_operator_info()->olp_list();
+  if (olp_list.empty()) {
     return;
+  }
 
-  const CellularService::OLP *result =
-      cellular_operator_info->GetOLPBySID(sid_string);
-  if (!result)
-    return;
-
-  CellularService::OLP olp;
-  olp.CopyFrom(*result);
-  string post_data = olp.GetPostData();
+  if (olp_list.size() > 1) {
+    SLOG(Cellular, 1) << "Found multiple online portals. Choosing the first.";
+  }
+  string post_data = olp_list[0].post_data;
   ReplaceSubstringsAfterOffset(&post_data, 0, "${esn}", cellular()->esn());
-  ReplaceSubstringsAfterOffset(&post_data, 0, "${mdn}",
-                               GetMdnForOLP(*cellular_operator));
+  ReplaceSubstringsAfterOffset(
+      &post_data, 0, "${mdn}",
+      GetMdnForOLP(cellular()->serving_operator_info()));
   ReplaceSubstringsAfterOffset(&post_data, 0, "${meid}", cellular()->meid());
   ReplaceSubstringsAfterOffset(&post_data, 0, "${oem}", "GOG2");
-  olp.SetPostData(post_data);
-  if (cellular()->service().get())
-    cellular()->service()->SetOLP(olp);
+  cellular()->service()->SetOLP(olp_list[0].url, olp_list[0].method, post_data);
 }
 
 void CellularCapabilityUniversalCDMA::GetProperties() {
@@ -356,7 +351,7 @@
   cellular()->service()->SetActivationState(
       GetActivationStateString(activation_state_));
   cellular()->service()->set_error(GetActivationErrorString(error));
-  UpdateOLP();
+  UpdateServiceOLP();
 }
 
 // static
diff --git a/cellular_capability_universal_cdma.h b/cellular_capability_universal_cdma.h
index 958f9d7..848b9bb 100644
--- a/cellular_capability_universal_cdma.h
+++ b/cellular_capability_universal_cdma.h
@@ -68,7 +68,7 @@
   // Inherited from CellularCapabilityUniversal.
   virtual void InitProxies() override;
   virtual void ReleaseProxies() override;
-  virtual void UpdateOLP() override;
+  virtual void UpdateServiceOLP() override;
 
   // Post-payment activation handlers.
   virtual void UpdatePendingActivationState() override;
@@ -85,7 +85,7 @@
   FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
               OnCDMARegistrationChanged);
   FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, PropertiesChanged);
-  FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, UpdateOLP);
+  FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, UpdateServiceOLP);
   FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, UpdateOperatorInfo);
   FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
               UpdateServiceActivationStateProperty);
diff --git a/cellular_capability_universal_cdma_unittest.cc b/cellular_capability_universal_cdma_unittest.cc
index f527f10..e54ce4c 100644
--- a/cellular_capability_universal_cdma_unittest.cc
+++ b/cellular_capability_universal_cdma_unittest.cc
@@ -28,6 +28,7 @@
 #include "shill/mock_mm1_modem_proxy.h"
 #include "shill/mock_mm1_modem_simple_proxy.h"
 #include "shill/mock_mm1_sim_proxy.h"
+#include "shill/mock_mobile_operator_info.h"
 #include "shill/mock_modem_info.h"
 #include "shill/mock_pending_activation_store.h"
 #include "shill/nice_mock_control.h"
@@ -58,6 +59,8 @@
         sim_proxy_(new mm1::MockSimProxy()),
         properties_proxy_(new MockDBusPropertiesProxy()),
         proxy_factory_(this),
+        mock_home_provider_info_(new MockMobileOperatorInfo(dispatcher)),
+        mock_serving_operator_info_(new MockMobileOperatorInfo(dispatcher)),
         cellular_(new Cellular(&modem_info_,
                                "",
                                kMachineAddress,
@@ -108,6 +111,13 @@
     capability_->modem_simple_proxy_.reset(modem_simple_proxy_.release());
   }
 
+  void SetMockMobileOperatorInfoObjects() {
+    CHECK(mock_home_provider_info_);
+    CHECK(mock_serving_operator_info_);
+    cellular_->set_home_provider_info(mock_home_provider_info_.release());
+    cellular_->set_serving_operator_info(mock_serving_operator_info_.release());
+  }
+
  protected:
   static const char kEsn[];
   static const char kMachineAddress[];
@@ -173,6 +183,8 @@
   scoped_ptr<mm1::MockSimProxy> sim_proxy_;
   scoped_ptr<MockDBusPropertiesProxy> properties_proxy_;
   TestProxyFactory proxy_factory_;
+  scoped_ptr<MockMobileOperatorInfo> mock_home_provider_info_;
+  scoped_ptr<MockMobileOperatorInfo> mock_serving_operator_info_;
   CellularRefPtr cellular_;
   MockCellularService *service_;
 };
@@ -342,41 +354,54 @@
 
 }
 
-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}");
+TEST_F(CellularCapabilityUniversalCDMAMainTest, UpdateServiceOLP) {
+  const MobileOperatorInfo::OnlinePortal kOlp {
+      "http://testurl",
+      "POST",
+      "esn=${esn}&mdn=${mdn}&meid=${meid}"};
+  const vector<MobileOperatorInfo::OnlinePortal> kOlpList {kOlp};
+  const string kUuidVzw = "vzw";
+  const string kUuidFoo = "foo";
 
+  MockMobileOperatorInfo *serving_operator_info =
+      mock_serving_operator_info_.get();
+  SetMockMobileOperatorInfoObjects();
   cellular_->set_esn("0");
   cellular_->set_mdn("10123456789");
   cellular_->set_meid("4");
-  capability_->sid_ = 1;
 
-  string sid_string = base::StringPrintf("%u", capability_->sid_);
-  EXPECT_CALL(*modem_info_.mock_cellular_operator_info(),
-              GetCellularOperatorBySID(sid_string))
-      .WillRepeatedly(Return(&cellular_operator));
-  EXPECT_CALL(*modem_info_.mock_cellular_operator_info(),
-              GetOLPBySID(sid_string))
-      .WillRepeatedly(Return(&test_olp));
 
+  serving_operator_info->SetEmptyDefaultsForProperties();
+  EXPECT_CALL(*serving_operator_info, IsMobileNetworkOperatorKnown())
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*serving_operator_info, olp_list())
+      .WillRepeatedly(ReturnRef(kOlpList));
+  EXPECT_CALL(*serving_operator_info, uuid())
+      .WillOnce(ReturnRef(kUuidVzw));
   SetService();
+  capability_->UpdateServiceOLP();
+  // Copy to simplify assertions below.
+  Stringmap vzw_olp = cellular_->service()->olp();
+  EXPECT_EQ("http://testurl", vzw_olp[kPaymentPortalURL]);
+  EXPECT_EQ("POST", vzw_olp[kPaymentPortalMethod]);
+  EXPECT_EQ("esn=0&mdn=0123456789&meid=4",
+            vzw_olp[kPaymentPortalPostData]);
+  Mock::VerifyAndClearExpectations(serving_operator_info);
 
-  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=10123456789&meid=4", olp.GetPostData());
+  serving_operator_info->SetEmptyDefaultsForProperties();
+  EXPECT_CALL(*serving_operator_info, IsMobileNetworkOperatorKnown())
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*serving_operator_info, olp_list())
+      .WillRepeatedly(ReturnRef(kOlpList));
+  EXPECT_CALL(*serving_operator_info, uuid())
+      .WillOnce(ReturnRef(kUuidFoo));
+  capability_->UpdateServiceOLP();
+  // Copy to simplify assertions below.
+  Stringmap olp = cellular_->service()->olp();
+  EXPECT_EQ("http://testurl", olp[kPaymentPortalURL]);
+  EXPECT_EQ("POST", olp[kPaymentPortalMethod]);
+  EXPECT_EQ("esn=0&mdn=10123456789&meid=4",
+            olp[kPaymentPortalPostData]);
 }
 
 TEST_F(CellularCapabilityUniversalCDMAMainTest, ActivateAutomatic) {
@@ -425,9 +450,9 @@
 }
 
 TEST_F(CellularCapabilityUniversalCDMAMainTest, IsServiceActivationRequired) {
-  CellularService::OLP olp;
+  CellularOperatorInfo::OLP olp;
   EXPECT_CALL(*modem_info_.mock_cellular_operator_info(), GetOLPBySID(_))
-      .WillOnce(Return((const CellularService::OLP *)NULL))
+      .WillOnce(Return((const CellularOperatorInfo::OLP *)NULL))
       .WillRepeatedly(Return(&olp));
   capability_->activation_state_ =
       MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED;
@@ -443,7 +468,7 @@
 
 TEST_F(CellularCapabilityUniversalCDMAMainTest,
        UpdateServiceActivationStateProperty) {
-  CellularService::OLP olp;
+  CellularOperatorInfo::OLP olp;
   EXPECT_CALL(*modem_info_.mock_cellular_operator_info(), GetOLPBySID(_))
       .WillRepeatedly(Return(&olp));
   EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
diff --git a/cellular_capability_universal_unittest.cc b/cellular_capability_universal_unittest.cc
index d9f65c3..2add654 100644
--- a/cellular_capability_universal_unittest.cc
+++ b/cellular_capability_universal_unittest.cc
@@ -31,6 +31,7 @@
 #include "shill/mock_mm1_modem_proxy.h"
 #include "shill/mock_mm1_modem_simple_proxy.h"
 #include "shill/mock_mm1_sim_proxy.h"
+#include "shill/mock_mobile_operator_info.h"
 #include "shill/mock_modem_info.h"
 #include "shill/mock_pending_activation_store.h"
 #include "shill/mock_profile.h"
@@ -74,6 +75,8 @@
         modem_simple_proxy_(new mm1::MockModemSimpleProxy()),
         sim_proxy_(new mm1::MockSimProxy()),
         properties_proxy_(new MockDBusPropertiesProxy()),
+        mock_home_provider_info_(new MockMobileOperatorInfo(dispatcher)),
+        mock_serving_operator_info_(new MockMobileOperatorInfo(dispatcher)),
         proxy_factory_(this),
         capability_(NULL),
         device_adaptor_(NULL),
@@ -189,6 +192,13 @@
     capability_->modem_simple_proxy_.reset(modem_simple_proxy_.release());
   }
 
+  void SetMockMobileOperatorInfoObjects() {
+    CHECK(mock_home_provider_info_);
+    CHECK(mock_serving_operator_info_);
+    cellular_->set_home_provider_info(mock_home_provider_info_.release());
+    cellular_->set_serving_operator_info(mock_serving_operator_info_.release());
+  }
+
   void ReleaseCapabilityProxies() {
     capability_->ReleaseProxies();
   }
@@ -306,6 +316,8 @@
   scoped_ptr<mm1::MockModemSimpleProxy> modem_simple_proxy_;
   scoped_ptr<mm1::MockSimProxy> sim_proxy_;
   scoped_ptr<MockDBusPropertiesProxy> properties_proxy_;
+  scoped_ptr<MockMobileOperatorInfo> mock_home_provider_info_;
+  scoped_ptr<MockMobileOperatorInfo> mock_serving_operator_info_;
   TestProxyFactory proxy_factory_;
   CellularCapabilityUniversal *capability_;  // Owned by |cellular_|.
   DeviceMockAdaptor *device_adaptor_;  // Owned by |cellular_|.
@@ -1562,71 +1574,91 @@
 }
 
 TEST_F(CellularCapabilityUniversalMainTest, GetMdnForOLP) {
-  CellularOperatorInfo::CellularOperator cellular_operator;
+  const string kVzwUUID = "vzw";
+  const string kFooUUID = "foo";
+  MockMobileOperatorInfo mock_operator_info(&dispatcher_);
 
+  mock_operator_info.SetEmptyDefaultsForProperties();
+  EXPECT_CALL(mock_operator_info, IsMobileNetworkOperatorKnown())
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(mock_operator_info, uuid()).WillRepeatedly(ReturnRef(kVzwUUID));
   capability_->subscription_state_ =
       CellularCapabilityUniversal::kSubscriptionStateUnknown;
 
-  cellular_operator.identifier_ = "vzw";
   cellular_->set_mdn("");
-  EXPECT_EQ("0000000000", capability_->GetMdnForOLP(cellular_operator));
+  EXPECT_EQ("0000000000", capability_->GetMdnForOLP(&mock_operator_info));
   cellular_->set_mdn("0123456789");
-  EXPECT_EQ("0123456789", capability_->GetMdnForOLP(cellular_operator));
+  EXPECT_EQ("0123456789", capability_->GetMdnForOLP(&mock_operator_info));
   cellular_->set_mdn("10123456789");
-  EXPECT_EQ("0123456789", capability_->GetMdnForOLP(cellular_operator));
+  EXPECT_EQ("0123456789", capability_->GetMdnForOLP(&mock_operator_info));
+
   cellular_->set_mdn("1021232333");
   capability_->subscription_state_ =
       CellularCapabilityUniversal::kSubscriptionStateUnprovisioned;
-  EXPECT_EQ("0000000000", capability_->GetMdnForOLP(cellular_operator));
+  EXPECT_EQ("0000000000", capability_->GetMdnForOLP(&mock_operator_info));
+  Mock::VerifyAndClearExpectations(&mock_operator_info);
 
-  cellular_operator.identifier_ = "foo";
+  mock_operator_info.SetEmptyDefaultsForProperties();
+  EXPECT_CALL(mock_operator_info, IsMobileNetworkOperatorKnown())
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(mock_operator_info, uuid()).WillRepeatedly(ReturnRef(kFooUUID));
+
   cellular_->set_mdn("");
-  EXPECT_EQ("", capability_->GetMdnForOLP(cellular_operator));
+  EXPECT_EQ("", capability_->GetMdnForOLP(&mock_operator_info));
   cellular_->set_mdn("0123456789");
-  EXPECT_EQ("0123456789", capability_->GetMdnForOLP(cellular_operator));
+  EXPECT_EQ("0123456789", capability_->GetMdnForOLP(&mock_operator_info));
   cellular_->set_mdn("10123456789");
-  EXPECT_EQ("10123456789", capability_->GetMdnForOLP(cellular_operator));
+  EXPECT_EQ("10123456789", capability_->GetMdnForOLP(&mock_operator_info));
 }
 
-TEST_F(CellularCapabilityUniversalMainTest, UpdateOLP) {
-  CellularOperatorInfo::CellularOperator cellular_operator;
+TEST_F(CellularCapabilityUniversalMainTest, UpdateServiceOLP) {
+  const MobileOperatorInfo::OnlinePortal kOlp {
+      "http://testurl",
+      "POST",
+      "imei=${imei}&imsi=${imsi}&mdn=${mdn}&min=${min}&iccid=${iccid}"};
+  const vector<MobileOperatorInfo::OnlinePortal> kOlpList {kOlp};
+  const string kUuidVzw = "vzw";
+  const string kUuidFoo = "foo";
 
-  CellularService::OLP test_olp;
-  test_olp.SetURL("http://testurl");
-  test_olp.SetMethod("POST");
-  test_olp.SetPostData("imei=${imei}&imsi=${imsi}&mdn=${mdn}&"
-                       "min=${min}&iccid=${iccid}");
-
+  MockMobileOperatorInfo *home_provider_info = mock_home_provider_info_.get();
+  SetMockMobileOperatorInfoObjects();
   cellular_->set_imei("1");
   cellular_->set_imsi("2");
   cellular_->set_mdn("10123456789");
   cellular_->set_min("5");
   cellular_->set_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));
-
+  home_provider_info->SetEmptyDefaultsForProperties();
+  EXPECT_CALL(*home_provider_info, IsMobileNetworkOperatorKnown())
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*home_provider_info, olp_list())
+      .WillRepeatedly(ReturnRef(kOlpList));
+  EXPECT_CALL(*home_provider_info, uuid())
+      .WillOnce(ReturnRef(kUuidVzw));
   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());
+  capability_->UpdateServiceOLP();
+  // Copy to simplify assertions below.
+  Stringmap vzw_olp = cellular_->service()->olp();
+  EXPECT_EQ("http://testurl", vzw_olp[kPaymentPortalURL]);
+  EXPECT_EQ("POST", vzw_olp[kPaymentPortalMethod]);
   EXPECT_EQ("imei=1&imsi=2&mdn=0123456789&min=5&iccid=6",
-            vzw_olp.GetPostData());
+            vzw_olp[kPaymentPortalPostData]);
+  Mock::VerifyAndClearExpectations(home_provider_info);
 
-  cellular_operator.identifier_ = "foo";
-  capability_->UpdateOLP();
-  const CellularService::OLP &olp = cellular_->service()->olp();
-  EXPECT_EQ("http://testurl", olp.GetURL());
-  EXPECT_EQ("POST", olp.GetMethod());
+  home_provider_info->SetEmptyDefaultsForProperties();
+  EXPECT_CALL(*home_provider_info, IsMobileNetworkOperatorKnown())
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*home_provider_info, olp_list())
+      .WillRepeatedly(ReturnRef(kOlpList));
+  EXPECT_CALL(*home_provider_info, uuid())
+      .WillOnce(ReturnRef(kUuidFoo));
+  capability_->UpdateServiceOLP();
+  // Copy to simplify assertions below.
+  Stringmap olp = cellular_->service()->olp();
+  EXPECT_EQ("http://testurl", olp[kPaymentPortalURL]);
+  EXPECT_EQ("POST", olp[kPaymentPortalMethod]);
   EXPECT_EQ("imei=1&imsi=2&mdn=10123456789&min=5&iccid=6",
-            olp.GetPostData());
+            olp[kPaymentPortalPostData]);
 }
 
 TEST_F(CellularCapabilityUniversalMainTest, IsMdnValid) {
@@ -1695,7 +1727,7 @@
       CellularCapabilityUniversal::kSubscriptionStateUnprovisioned;
   cellular_->set_sim_identifier("");
   cellular_->set_mdn("0000000000");
-  CellularService::OLP olp;
+  CellularOperatorInfo::OLP olp;
   EXPECT_CALL(*modem_info_.mock_cellular_operator_info(), GetOLPByMCCMNC(_))
       .WillRepeatedly(Return(&olp));
 
@@ -2042,9 +2074,9 @@
   cellular_->set_mdn("0000000000");
   EXPECT_FALSE(capability_->IsServiceActivationRequired());
 
-  CellularService::OLP olp;
+  CellularOperatorInfo::OLP olp;
   EXPECT_CALL(*modem_info_.mock_cellular_operator_info(), GetOLPByMCCMNC(_))
-      .WillOnce(Return((const CellularService::OLP *)NULL))
+      .WillOnce(Return((const CellularOperatorInfo::OLP *)NULL))
       .WillRepeatedly(Return(&olp));
   EXPECT_FALSE(capability_->IsServiceActivationRequired());
 
diff --git a/cellular_operator_info.cc b/cellular_operator_info.cc
index da3fdce..caca4bc 100644
--- a/cellular_operator_info.cc
+++ b/cellular_operator_info.cc
@@ -11,6 +11,7 @@
 #include <base/strings/string_number_conversions.h>
 #include <base/strings/string_split.h>
 #include <base/strings/string_util.h>
+#include <chromeos/dbus/service_constants.h>
 
 #include "shill/logging.h"
 
@@ -21,6 +22,50 @@
 
 namespace shill {
 
+CellularOperatorInfo::OLP::OLP() {
+  SetURL("");
+  SetMethod("");
+  SetPostData("");
+}
+
+CellularOperatorInfo::OLP::~OLP() {}
+
+void CellularOperatorInfo::OLP::CopyFrom(const OLP &olp) {
+  dict_ = olp.dict_;
+}
+
+bool CellularOperatorInfo::OLP::Equals(const OLP &olp) const {
+  return dict_ == olp.dict_;
+}
+
+const string &CellularOperatorInfo::OLP::GetURL() const {
+  return dict_.find(kPaymentPortalURL)->second;
+}
+
+void CellularOperatorInfo::OLP::SetURL(const string &url) {
+  dict_[kPaymentPortalURL] = url;
+}
+
+const string &CellularOperatorInfo::OLP::GetMethod() const {
+  return dict_.find(kPaymentPortalMethod)->second;
+}
+
+void CellularOperatorInfo::OLP::SetMethod(const string &method) {
+  dict_[kPaymentPortalMethod] = method;
+}
+
+const string &CellularOperatorInfo::OLP::GetPostData() const {
+  return dict_.find(kPaymentPortalPostData)->second;
+}
+
+void CellularOperatorInfo::OLP::SetPostData(const string &post_data) {
+  dict_[kPaymentPortalPostData] = post_data;
+}
+
+const Stringmap &CellularOperatorInfo::OLP::ToDict() const {
+  return dict_;
+}
+
 namespace {
 
 typedef vector<const CellularOperatorInfo::CellularOperator *>
@@ -470,7 +515,7 @@
       LOG(ERROR) << "Badly formed \"apn\" entry.";
       return false;
     }
-    CellularService::OLP *olp = new CellularService::OLP();
+    CellularOperatorInfo::OLP *olp = new CellularOperatorInfo::OLP();
     olp->SetMethod(fields[0]);
     olp->SetURL(fields[1]);
     olp->SetPostData(fields[2]);
@@ -605,7 +650,7 @@
   return providers;
 }
 
-const CellularService::OLP *
+const CellularOperatorInfo::OLP *
 CellularOperatorInfo::GetOLPByMCCMNC(const string &mccmnc) const {
   SLOG(Cellular, 2) << __func__ << "(" << FormattedMCCMNC(mccmnc) << ")";
 
@@ -627,7 +672,7 @@
   return provider->olp_list_[index];
 }
 
-const CellularService::OLP *
+const CellularOperatorInfo::OLP *
 CellularOperatorInfo::GetOLPBySID(const string &sid) const {
   SLOG(Cellular, 2) << __func__ << "(" << FormattedSID(sid) << ")";
 
diff --git a/cellular_operator_info.h b/cellular_operator_info.h
index 5f2e069..ef7b44c 100644
--- a/cellular_operator_info.h
+++ b/cellular_operator_info.h
@@ -70,6 +70,34 @@
     std::string password;
   };
 
+  // TODO(pprabhu) This is a temporary addition to CellularOperatorInfo, to make
+  // it easy to transition the rest of the code away from using ::OLP.
+  // CellularOperatorInfo is soon going away anyway.
+  class OLP {
+   public:
+    OLP();
+    ~OLP();
+
+    void CopyFrom(const OLP &olp);
+    bool Equals(const OLP &olp) const;
+
+    const std::string &GetURL() const;
+    void SetURL(const std::string &url);
+
+    const std::string &GetMethod() const;
+    void SetMethod(const std::string &method);
+
+    const std::string &GetPostData() const;
+    void SetPostData(const std::string &post_data);
+
+    const Stringmap &ToDict() const;
+
+   private:
+    Stringmap dict_;
+
+    DISALLOW_COPY_AND_ASSIGN(OLP);
+  };
+
   // This class contains all the necessary information for shill to register
   // with and establish a connection to a mobile network.
   class CellularOperator {
@@ -115,7 +143,7 @@
     // All Online Payment Portal URLs associated with this carrier entry. There
     // are usually multiple OLPs based on access technology and it is up to the
     // application to use the appropriate one.
-    const ScopedVector<CellularService::OLP> &olp_list() const {
+    const ScopedVector<CellularOperatorInfo::OLP> &olp_list() const {
         return olp_list_;
     }
 
@@ -149,7 +177,7 @@
     std::vector<std::string> sid_list_;
     std::vector<LocalizedName> name_list_;
     ScopedVector<MobileAPN> apn_list_;
-    ScopedVector<CellularService::OLP> olp_list_;
+    ScopedVector<CellularOperatorInfo::OLP> olp_list_;
     std::map<std::string, uint32> mccmnc_to_olp_idx_;
     std::map<std::string, uint32> sid_to_olp_idx_;
     bool is_primary_;
@@ -187,12 +215,13 @@
 
   // Gets the online payment portal info of the operator with MCCMNC |mccmnc|.
   // If found, returns a pointer to the matching OLP.
-  virtual const CellularService::OLP *GetOLPByMCCMNC(
+  virtual const CellularOperatorInfo::OLP *GetOLPByMCCMNC(
       const std::string &mccmnc) const;
 
   // Gets the online payment portal info of the operator with SID |sid|.
   // If found, returns a pointer to the matching OLP.
-  virtual const CellularService::OLP *GetOLPBySID(const std::string &sid) const;
+  virtual const CellularOperatorInfo::OLP *GetOLPBySID(
+        const std::string &sid) const;
 
   // Returns a list of all operators.
   const ScopedVector<CellularOperator> &operators() const;
diff --git a/cellular_operator_info_unittest.cc b/cellular_operator_info_unittest.cc
index 5ac0f44..4714fb8 100644
--- a/cellular_operator_info_unittest.cc
+++ b/cellular_operator_info_unittest.cc
@@ -227,7 +227,7 @@
 TEST_F(CellularOperatorInfoTest, GetOLPByMCCMNC) {
   EXPECT_TRUE(info_.Load(info_file_path_));
 
-  const CellularService::OLP *olp = NULL;
+  const CellularOperatorInfo::OLP *olp = NULL;
   EXPECT_TRUE((olp = info_.GetOLPByMCCMNC("000001")));
   EXPECT_EQ("https://testurl", olp->GetURL());
   EXPECT_EQ("POST", olp->GetMethod());
@@ -255,7 +255,7 @@
 TEST_F(CellularOperatorInfoTest, GetOLPBySID) {
   EXPECT_TRUE(info_.Load(info_file_path_));
 
-  const CellularService::OLP *olp = NULL;
+  const CellularOperatorInfo::OLP *olp = NULL;
   EXPECT_TRUE((olp = info_.GetOLPBySID("1")));
   EXPECT_EQ("https://testurl", olp->GetURL());
   EXPECT_EQ("POST", olp->GetMethod());
diff --git a/cellular_service.cc b/cellular_service.cc
index 78607fc..cf3a82e 100644
--- a/cellular_service.cc
+++ b/cellular_service.cc
@@ -31,9 +31,6 @@
 
 // TODO(petkov): Add these to system_api/dbus/service_constants.h
 namespace {
-const char kKeyOLPURL[] = "url";
-const char kKeyOLPMethod[] = "method";
-const char kKeyOLPPostData[] = "postdata";
 const char kCellularPPPUsernameProperty[] = "Cellular.PPP.Username";
 const char kCellularPPPPasswordProperty[] = "Cellular.PPP.Password";
 }  // namespace
@@ -54,50 +51,6 @@
   return false;
 }
 
-CellularService::OLP::OLP() {
-  SetURL("");
-  SetMethod("");
-  SetPostData("");
-}
-
-CellularService::OLP::~OLP() {}
-
-void CellularService::OLP::CopyFrom(const OLP &olp) {
-  dict_ = olp.dict_;
-}
-
-bool CellularService::OLP::Equals(const OLP &olp) const {
-  return dict_ == olp.dict_;
-}
-
-const string &CellularService::OLP::GetURL() const {
-  return dict_.find(kKeyOLPURL)->second;
-}
-
-void CellularService::OLP::SetURL(const string &url) {
-  dict_[kKeyOLPURL] = url;
-}
-
-const string &CellularService::OLP::GetMethod() const {
-  return dict_.find(kKeyOLPMethod)->second;
-}
-
-void CellularService::OLP::SetMethod(const string &method) {
-  dict_[kKeyOLPMethod] = method;
-}
-
-const string &CellularService::OLP::GetPostData() const {
-  return dict_.find(kKeyOLPPostData)->second;
-}
-
-void CellularService::OLP::SetPostData(const string &post_data) {
-  dict_[kKeyOLPPostData] = post_data;
-}
-
-const Stringmap &CellularService::OLP::ToDict() const {
-  return dict_;
-}
-
 CellularService::CellularService(ModemInfo *modem_info,
                                  const CellularRefPtr &device)
     : Service(modem_info->control_interface(), modem_info->dispatcher(),
@@ -121,7 +74,7 @@
   HelpRegisterDerivedBool(kOutOfCreditsProperty,
                           &CellularService::IsOutOfCredits,
                           NULL);
-  store->RegisterConstStringmap(kPaymentPortalProperty, &olp_.ToDict());
+  store->RegisterConstStringmap(kPaymentPortalProperty, &olp_);
   store->RegisterConstString(kRoamingStateProperty, &roaming_state_);
   store->RegisterConstStringmap(kServingOperatorProperty,
                                 &serving_operator_.ToDict());
@@ -414,13 +367,19 @@
   SetConnectableFull(state != kActivationStateNotActivated);
 }
 
-void CellularService::SetOLP(const OLP &olp) {
-  if (olp_.Equals(olp)) {
+void CellularService::SetOLP(const string &url,
+                             const string &method,
+                             const string &post_data) {
+  Stringmap olp;
+  olp[kPaymentPortalURL] = url;
+  olp[kPaymentPortalMethod] = method;
+  olp[kPaymentPortalPostData] = post_data;
+
+  if (olp_ == olp) {
     return;
   }
-  olp_.CopyFrom(olp);
-  adaptor()->EmitStringmapChanged(kPaymentPortalProperty,
-                                  olp.ToDict());
+  olp_ = olp;
+  adaptor()->EmitStringmapChanged(kPaymentPortalProperty, olp);
 }
 
 void CellularService::SetUsageURL(const string &url) {
diff --git a/cellular_service.h b/cellular_service.h
index 910763b..749a555 100644
--- a/cellular_service.h
+++ b/cellular_service.h
@@ -27,33 +27,6 @@
 
 class CellularService : public Service {
  public:
-  // Online payment portal.
-  // TODO(armansito): Move this to CellularOperatorInfo.
-  class OLP {
-   public:
-    OLP();
-    ~OLP();
-
-    void CopyFrom(const OLP &olp);
-    bool Equals(const OLP &olp) const;
-
-    const std::string &GetURL() const;
-    void SetURL(const std::string &url);
-
-    const std::string &GetMethod() const;
-    void SetMethod(const std::string &method);
-
-    const std::string &GetPostData() const;
-    void SetPostData(const std::string &post_data);
-
-    const Stringmap &ToDict() const;
-
-   private:
-    Stringmap dict_;
-
-    DISALLOW_COPY_AND_ASSIGN(OLP);
-  };
-
   CellularService(ModemInfo *modem_info,
                   const CellularRefPtr &device);
   virtual ~CellularService();
@@ -83,8 +56,10 @@
       return activation_state_;
   }
 
-  void SetOLP(const OLP &olp);
-  const OLP &olp() const { return olp_; }
+  void SetOLP(const std::string &url,
+              const std::string &method,
+              const std::string &post_data);
+  const Stringmap &olp() const { return olp_; }
 
   void SetUsageURL(const std::string &url);
   const std::string &usage_url() const { return usage_url_; }
@@ -216,7 +191,7 @@
   Cellular::Operator serving_operator_;
   std::string network_technology_;
   std::string roaming_state_;
-  OLP olp_;
+  Stringmap olp_;
   std::string usage_url_;
   Stringmap apn_info_;
   Stringmap last_good_apn_info_;
diff --git a/cellular_service_unittest.cc b/cellular_service_unittest.cc
index 9aacf76..b8908a5 100644
--- a/cellular_service_unittest.cc
+++ b/cellular_service_unittest.cc
@@ -178,18 +178,24 @@
 }
 
 TEST_F(CellularServiceTest, SetOLP) {
+  const char kMethod[] = "GET";
+  const char kURL[] = "payment.url";
+  const char kPostData[] = "post_man";
+  Stringmap olp;
+
+  service_->SetOLP("", "", "");
+  olp = service_->olp();  // Copy to simplify assertions below.
+  EXPECT_EQ("", olp[kPaymentPortalURL]);
+  EXPECT_EQ("", olp[kPaymentPortalMethod]);
+  EXPECT_EQ("", olp[kPaymentPortalPostData]);
+
   EXPECT_CALL(*adaptor_,
               EmitStringmapChanged(kPaymentPortalProperty, _));
-  static const char kURL[] = "payment.url";
-  static const char kMethod[] = "GET";
-  CellularService::OLP olp;
-  service_->SetOLP(olp);
-  olp.SetURL(kURL);
-  olp.SetMethod(kMethod);
-  service_->SetOLP(olp);
-  EXPECT_EQ(kURL, service_->olp().GetURL());
-  EXPECT_EQ(kMethod, service_->olp().GetMethod());
-  service_->SetOLP(olp);
+  service_->SetOLP(kURL, kMethod, kPostData);
+  olp = service_->olp();  // Copy to simplify assertions below.
+  EXPECT_EQ(kURL, olp[kPaymentPortalURL]);
+  EXPECT_EQ(kMethod, olp[kPaymentPortalMethod]);
+  EXPECT_EQ(kPostData, olp[kPaymentPortalPostData]);
 }
 
 TEST_F(CellularServiceTest, SetUsageURL) {
diff --git a/cellular_unittest.cc b/cellular_unittest.cc
index df15be9..ed2a228 100644
--- a/cellular_unittest.cc
+++ b/cellular_unittest.cc
@@ -751,21 +751,6 @@
   device_->SelectService(NULL);
 }
 
-TEST_F(CellularTest, CreateService) {
-  SetCellularType(Cellular::kTypeCDMA);
-  static const char kPaymentURL[] = "https://payment.url";
-  static const char kUsageURL[] = "https://usage.url";
-  device_->home_provider_.SetName(kTestCarrier);
-  GetCapabilityCDMA()->olp_.SetURL(kPaymentURL);
-  GetCapabilityCDMA()->usage_url_ = kUsageURL;
-  device_->CreateService();
-  ASSERT_TRUE(device_->service_.get());
-  EXPECT_EQ(kPaymentURL, device_->service_->olp().GetURL());
-  EXPECT_EQ(kUsageURL, device_->service_->usage_url());
-  EXPECT_EQ(kTestCarrier, device_->service_->serving_operator().GetName());
-  ASSERT_FALSE(device_->service_->activate_over_non_cellular_network());
-}
-
 TEST_F(CellularTest, ServiceFriendlyName) {
   // Test that the name created for the service is sensible under different
   // scenarios w.r.t. information about the mobile network operator.
@@ -776,6 +761,8 @@
   const string home_provider_name {"HomeProviderName"};
   const string serving_operator_name {"ServingOperatorName"};
   SetCellularType(Cellular::kTypeCDMA);
+  // We are not testing the behaviour of capabilities here.
+  device_->mobile_operator_info_observer_->set_capability(NULL);
 
   // (1) Service created, MNO not known => Default name.
   EXPECT_CALL(*mock_home_provider_info_, IsMobileNetworkOperatorKnown())
@@ -926,6 +913,8 @@
   const string kSimIdentifier = "12345123451234512345";
 
   SetCellularType(Cellular::kTypeCDMA);
+  // We are not testing the behaviour of capabilities here.
+  device_->mobile_operator_info_observer_->set_capability(NULL);
   ON_CALL(*mock_home_provider_info_, IsMobileNetworkOperatorKnown())
       .WillByDefault(Return(false));
 
@@ -1154,7 +1143,7 @@
 
   // Service activation is needed
   device_->set_mdn("0000000000");
-  CellularService::OLP olp;
+  CellularOperatorInfo::OLP olp;
   EXPECT_CALL(*modem_info_.mock_cellular_operator_info(), GetOLPByMCCMNC(_))
       .WillRepeatedly(Return(&olp));
   EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
diff --git a/mobile_operator_info.h b/mobile_operator_info.h
index a180127..ae053d2 100644
--- a/mobile_operator_info.h
+++ b/mobile_operator_info.h
@@ -168,7 +168,7 @@
   // All Online Payment Portal URLs associated with this carrier entry. There
   // are usually multiple OLPs based on access technology and it is up to the
   // application to use the appropriate one.
-  const std::vector<OnlinePortal> &olp_list() const;
+  virtual const std::vector<OnlinePortal> &olp_list() const;
 
   // The number to dial for automatic activation.
   const std::string &activation_code() const;
diff --git a/mock_cellular_operator_info.h b/mock_cellular_operator_info.h
index 0035dfe..b65488c 100644
--- a/mock_cellular_operator_info.h
+++ b/mock_cellular_operator_info.h
@@ -19,12 +19,13 @@
   virtual ~MockCellularOperatorInfo();
 
   MOCK_METHOD1(Load, bool(const base::FilePath &info_file_path));
-  MOCK_CONST_METHOD1(GetOLPByMCCMNC,
-                     const CellularService::OLP *(const std::string &mccmnc));
+  MOCK_CONST_METHOD1(
+      GetOLPByMCCMNC,
+      const CellularOperatorInfo::OLP *(const std::string &mccmnc));
   MOCK_CONST_METHOD1(GetCellularOperatorByMCCMNC,
                      const CellularOperator *(const std::string &mccmnc));
   MOCK_CONST_METHOD1(GetOLPBySID,
-                     const CellularService::OLP *(const std::string &sid));
+                     const CellularOperatorInfo::OLP *(const std::string &sid));
   MOCK_CONST_METHOD1(GetCellularOperatorBySID,
                      const CellularOperator *(const std::string &sid));
 };
diff --git a/mock_mobile_operator_info.cc b/mock_mobile_operator_info.cc
index c4b6ab9..4f3d197 100644
--- a/mock_mobile_operator_info.cc
+++ b/mock_mobile_operator_info.cc
@@ -15,6 +15,7 @@
 
 void MockMobileOperatorInfo::SetEmptyDefaultsForProperties() {
   ON_CALL(*this, mccmnc()).WillByDefault(ReturnRef(empty_mccmnc_));
+  ON_CALL(*this, olp_list()).WillByDefault(ReturnRef(empty_olp_list_));
   ON_CALL(*this, operator_name())
       .WillByDefault(ReturnRef(empty_operator_name_));
   ON_CALL(*this, uuid()).WillByDefault(ReturnRef(empty_uuid_));
diff --git a/mock_mobile_operator_info.h b/mock_mobile_operator_info.h
index 49cbb2a..a0ad489 100644
--- a/mock_mobile_operator_info.h
+++ b/mock_mobile_operator_info.h
@@ -6,6 +6,7 @@
 #define SHILL_MOCK_MOBILE_OPERATOR_INFO_H_
 
 #include <string>
+#include <vector>
 
 #include <gmock/gmock.h>
 
@@ -23,6 +24,8 @@
   MOCK_CONST_METHOD0(IsMobileNetworkOperatorKnown, bool());
 
   MOCK_CONST_METHOD0(mccmnc, const std::string &());
+  MOCK_CONST_METHOD0(olp_list,
+                     const std::vector<MobileOperatorInfo::OnlinePortal> &());
   MOCK_CONST_METHOD0(operator_name, const std::string &());
   MOCK_CONST_METHOD0(uuid, const std::string &());
 
@@ -32,6 +35,7 @@
 
  private:
   std::string empty_mccmnc_;
+  std::vector<MobileOperatorInfo::OnlinePortal> empty_olp_list_;
   std::string empty_operator_name_;
   std::string empty_uuid_;
 };