Home | History | Annotate | Download | only in mobile
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/chromeos/mobile/mobile_activator.h"
      6 
      7 #include "base/message_loop/message_loop.h"
      8 #include "base/values.h"
      9 #include "chromeos/dbus/dbus_thread_manager.h"
     10 #include "chromeos/network/network_connection_handler.h"
     11 #include "chromeos/network/network_handler.h"
     12 #include "chromeos/network/network_state.h"
     13 #include "chromeos/network/network_state_handler.h"
     14 #include "content/public/browser/browser_thread.h"
     15 #include "testing/gmock/include/gmock/gmock.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 #include "third_party/cros_system_api/dbus/service_constants.h"
     18 
     19 using std::string;
     20 
     21 using content::BrowserThread;
     22 using testing::_;
     23 using testing::Eq;
     24 using testing::Invoke;
     25 using testing::Mock;
     26 using testing::Return;
     27 using testing::WithArgs;
     28 
     29 namespace {
     30 
     31 const char kTestServicePath[] = "/a/service/path";
     32 
     33 const size_t kNumOTASPStates = 3;
     34 
     35 chromeos::MobileActivator::PlanActivationState kOTASPStates[kNumOTASPStates] = {
     36   chromeos::MobileActivator::PLAN_ACTIVATION_TRYING_OTASP,
     37   chromeos::MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
     38   chromeos::MobileActivator::PLAN_ACTIVATION_OTASP,
     39 };
     40 
     41 }  // namespace
     42 namespace chromeos {
     43 
     44 class TestMobileActivator : public MobileActivator {
     45  public:
     46   explicit TestMobileActivator(NetworkState* cellular_network) :
     47         cellular_network_(cellular_network) {
     48     // Provide reasonable defaults for basic things we're usually not testing.
     49     ON_CALL(*this, ChangeState(_, _, _))
     50         .WillByDefault(WithArgs<1>(
     51             Invoke(this, &TestMobileActivator::set_state_for_test)));
     52   }
     53   virtual ~TestMobileActivator() {}
     54 
     55   MOCK_METHOD3(RequestCellularActivation,
     56                void(const NetworkState*,
     57                     const base::Closure&,
     58                     const network_handler::ErrorCallback&));
     59   MOCK_METHOD3(ChangeState, void(const NetworkState*,
     60                                  MobileActivator::PlanActivationState,
     61                                  std::string));
     62   MOCK_METHOD0(GetDefaultNetwork, const NetworkState*());
     63   MOCK_METHOD1(EvaluateCellularNetwork, void(const NetworkState*));
     64   MOCK_METHOD0(SignalCellularPlanPayment, void(void));
     65   MOCK_METHOD0(StartOTASPTimer, void(void));
     66   MOCK_CONST_METHOD0(HasRecentCellularPlanPayment, bool(void));
     67   MOCK_METHOD1(ConnectNetwork, void(const NetworkState*));
     68 
     69   virtual const NetworkState* GetNetworkState(const std::string& service_path) {
     70     return cellular_network_;
     71   }
     72 
     73   void InvokeStartActivation() {
     74     StartActivation();
     75   }
     76 
     77   void InvokeHandlePortalLoaded(bool success) {
     78     HandlePortalLoaded(success);
     79   }
     80 
     81   void InvokeHandleSetTransactionStatus(bool success) {
     82     HandleSetTransactionStatus(success);
     83   }
     84 
     85   PlanActivationState InvokePickNextState(
     86       const NetworkState* network,
     87       std::string* error_description) const {
     88     return PickNextState(network, error_description);
     89   }
     90 
     91   void InvokeChangeState(const NetworkState* network,
     92                          MobileActivator::PlanActivationState new_state,
     93                          std::string error_description) {
     94     MobileActivator::ChangeState(network, new_state, error_description);
     95   }
     96 
     97  private:
     98   void DCheckOnThread(const BrowserThread::ID id) const {}
     99 
    100   NetworkState* cellular_network_;
    101 
    102   DISALLOW_COPY_AND_ASSIGN(TestMobileActivator);
    103 };
    104 
    105 class MobileActivatorTest : public testing::Test {
    106  public:
    107   MobileActivatorTest()
    108       : cellular_network_(string(kTestServicePath)),
    109         mobile_activator_(&cellular_network_) {
    110     cellular_network_.PropertyChanged(shill::kTypeProperty,
    111                                       base::StringValue(shill::kTypeCellular));
    112   }
    113   virtual ~MobileActivatorTest() {}
    114 
    115  protected:
    116   virtual void SetUp() {
    117     DBusThreadManager::Initialize();
    118     NetworkHandler::Initialize();
    119   }
    120   virtual void TearDown() {
    121     NetworkHandler::Shutdown();
    122     DBusThreadManager::Shutdown();
    123   }
    124 
    125   void set_activator_state(const MobileActivator::PlanActivationState state) {
    126     mobile_activator_.set_state_for_test(state);
    127   }
    128   void set_network_activation_type(const std::string& activation_type) {
    129     cellular_network_.activation_type_ = activation_type;
    130   }
    131   void set_network_activation_state(const std::string& activation_state) {
    132     cellular_network_.activation_state_ = activation_state;
    133   }
    134   void set_connection_state(const std::string& state) {
    135     cellular_network_.visible_ = true;
    136     cellular_network_.connection_state_ = state;
    137   }
    138 
    139   base::MessageLoop message_loop_;
    140   NetworkState cellular_network_;
    141   TestMobileActivator mobile_activator_;
    142 
    143  private:
    144   DISALLOW_COPY_AND_ASSIGN(MobileActivatorTest);
    145 };
    146 
    147 TEST_F(MobileActivatorTest, OTAHasNetworkConnection) {
    148   // Make sure if we have a network connection, the mobile activator does not
    149   // connect to the network.
    150   EXPECT_CALL(mobile_activator_, GetDefaultNetwork())
    151       .WillRepeatedly(Return(&cellular_network_));
    152   EXPECT_CALL(mobile_activator_, ConnectNetwork(_))
    153       .Times(0);
    154   set_connection_state(shill::kStatePortal);
    155   set_network_activation_type(shill::kActivationTypeOTA);
    156   set_network_activation_state(shill::kActivationStateNotActivated);
    157   mobile_activator_.InvokeStartActivation();
    158   EXPECT_EQ(mobile_activator_.state(),
    159             MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING);
    160 }
    161 
    162 TEST_F(MobileActivatorTest, OTANoNetworkConnection) {
    163   // Make sure if we don't have a network connection, the mobile activator
    164   // connects to the network.
    165   EXPECT_CALL(mobile_activator_, GetDefaultNetwork())
    166       .WillRepeatedly(Return(static_cast<NetworkState*>(NULL)));
    167   EXPECT_CALL(mobile_activator_, ConnectNetwork(&cellular_network_));
    168   set_connection_state(shill::kStateIdle);
    169   set_network_activation_type(shill::kActivationTypeOTA);
    170   set_network_activation_state(shill::kActivationStateNotActivated);
    171   mobile_activator_.InvokeStartActivation();
    172   EXPECT_EQ(mobile_activator_.state(),
    173             MobileActivator::PLAN_ACTIVATION_WAITING_FOR_CONNECTION);
    174 }
    175 
    176 TEST_F(MobileActivatorTest, OTAActivationFlow) {
    177   // Once a network connection is available, the OTA flow should look like the
    178   // following:
    179   //   - Loading payment portal
    180   //   - Showing payment portal
    181   //   - (User fills out payment portal and submits information)
    182   //   - Activation complete
    183   EXPECT_CALL(mobile_activator_, GetDefaultNetwork())
    184       .WillRepeatedly(Return(&cellular_network_));
    185   set_connection_state(shill::kStateOnline);
    186   set_network_activation_type(shill::kActivationTypeOTA);
    187   set_network_activation_state(shill::kActivationStateNotActivated);
    188   mobile_activator_.InvokeStartActivation();
    189   EXPECT_EQ(mobile_activator_.state(),
    190             MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING);
    191   mobile_activator_.InvokeHandlePortalLoaded(true);
    192   EXPECT_EQ(mobile_activator_.state(),
    193             MobileActivator::PLAN_ACTIVATION_SHOWING_PAYMENT);
    194   mobile_activator_.InvokeHandleSetTransactionStatus(true);
    195   EXPECT_EQ(mobile_activator_.state(), MobileActivator::PLAN_ACTIVATION_DONE);
    196 }
    197 
    198 TEST_F(MobileActivatorTest, OTASPBasicFlowForNewDevices) {
    199   // In a new device, we aren't connected to Verizon, we start at START
    200   // because we haven't paid Verizon (ever), and the modem isn't even partially
    201   // activated.
    202   std::string error_description;
    203   set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
    204   set_connection_state(shill::kStateIdle);
    205   set_network_activation_type(shill::kActivationTypeOTASP);
    206   set_network_activation_state(shill::kActivationStateNotActivated);
    207   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
    208             mobile_activator_.InvokePickNextState(&cellular_network_,
    209                                                   &error_description));
    210   // Now behave as if ChangeState() has initiated an activation.
    211   set_activator_state(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION);
    212   set_network_activation_state(shill::kActivationStateActivating);
    213   // We'll sit in this state while we wait for the OTASP to finish.
    214   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
    215             mobile_activator_.InvokePickNextState(&cellular_network_,
    216                                                   &error_description));
    217   set_network_activation_state(shill::kActivationStatePartiallyActivated);
    218   // We'll sit in this state until we go online as well.
    219   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
    220             mobile_activator_.InvokePickNextState(&cellular_network_,
    221                                                   &error_description));
    222   set_connection_state(shill::kStatePortal);
    223   // After we go online, we go back to START, which acts as a jumping off
    224   // point for the two types of initial OTASP.
    225   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_START,
    226             mobile_activator_.InvokePickNextState(&cellular_network_,
    227                                                   &error_description));
    228   set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
    229   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP,
    230             mobile_activator_.InvokePickNextState(&cellular_network_,
    231                                                   &error_description));
    232   // Very similar things happen while we're trying OTASP.
    233   set_activator_state(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP);
    234   set_network_activation_state(shill::kActivationStateActivating);
    235   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP,
    236             mobile_activator_.InvokePickNextState(&cellular_network_,
    237                                                   &error_description));
    238   set_network_activation_state(shill::kActivationStatePartiallyActivated);
    239   set_connection_state(shill::kStatePortal);
    240   // And when we come back online again and aren't activating, load the portal.
    241   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING,
    242             mobile_activator_.InvokePickNextState(&cellular_network_,
    243                                                   &error_description));
    244   // The JS drives us through the payment portal.
    245   set_activator_state(MobileActivator::PLAN_ACTIVATION_SHOWING_PAYMENT);
    246   // The JS also calls us to signal that the portal is done.  This triggers us
    247   // to start our final OTASP via the aptly named StartOTASP().
    248   EXPECT_CALL(mobile_activator_, SignalCellularPlanPayment());
    249   EXPECT_CALL(mobile_activator_,
    250               ChangeState(Eq(&cellular_network_),
    251                           Eq(MobileActivator::PLAN_ACTIVATION_START_OTASP),
    252                           _));
    253   EXPECT_CALL(mobile_activator_,
    254               EvaluateCellularNetwork(Eq(&cellular_network_)));
    255   mobile_activator_.InvokeHandleSetTransactionStatus(true);
    256   // Evaluate state will defer to PickNextState to select what to do now that
    257   // we're in START_ACTIVATION.  PickNextState should decide to start a final
    258   // OTASP.
    259   set_activator_state(MobileActivator::PLAN_ACTIVATION_START_OTASP);
    260   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_OTASP,
    261             mobile_activator_.InvokePickNextState(&cellular_network_,
    262                                                   &error_description));
    263   // Similarly to TRYING_OTASP and INITIATING_OTASP above...
    264   set_activator_state(MobileActivator::PLAN_ACTIVATION_OTASP);
    265   set_network_activation_state(shill::kActivationStateActivating);
    266   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_OTASP,
    267             mobile_activator_.InvokePickNextState(&cellular_network_,
    268                                                   &error_description));
    269   set_network_activation_state(shill::kActivationStateActivated);
    270   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_DONE,
    271             mobile_activator_.InvokePickNextState(&cellular_network_,
    272                                                   &error_description));
    273 }
    274 
    275 // A fake for MobileActivator::RequestCellularActivation that always succeeds.
    276 void FakeRequestCellularActivationSuccess(
    277     const NetworkState* network,
    278     const base::Closure& success_callback,
    279     const network_handler::ErrorCallback& error_callback) {
    280   success_callback.Run();
    281 }
    282 
    283 // A fake for MobileActivator::RequestCellularActivation that always fails.
    284 void FakeRequestCellularActivationFailure(
    285     const NetworkState* network,
    286     const base::Closure& success_callback,
    287     const network_handler::ErrorCallback& error_callback) {
    288   scoped_ptr<base::DictionaryValue> value;
    289   error_callback.Run("", value.Pass());
    290 }
    291 
    292 TEST_F(MobileActivatorTest, OTASPScheduling) {
    293   const std::string error;
    294   for (size_t i = 0; i < kNumOTASPStates; ++i) {
    295     // When activation works, we start a timer to watch for success.
    296     EXPECT_CALL(mobile_activator_, RequestCellularActivation(_, _, _))
    297         .Times(1)
    298         .WillOnce(Invoke(FakeRequestCellularActivationSuccess));
    299     EXPECT_CALL(mobile_activator_, StartOTASPTimer())
    300          .Times(1);
    301     set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
    302     mobile_activator_.InvokeChangeState(&cellular_network_,
    303                                         kOTASPStates[i],
    304                                         error);
    305 
    306     // When activation fails, it's an error, unless we're trying for the final
    307     // OTASP, in which case we try again via DELAY_OTASP.
    308     EXPECT_CALL(mobile_activator_, RequestCellularActivation(_, _, _))
    309         .Times(1)
    310         .WillOnce(Invoke(FakeRequestCellularActivationFailure));
    311     if (kOTASPStates[i] == MobileActivator::PLAN_ACTIVATION_OTASP) {
    312       EXPECT_CALL(mobile_activator_, ChangeState(
    313           Eq(&cellular_network_),
    314           Eq(MobileActivator::PLAN_ACTIVATION_DELAY_OTASP),
    315           _));
    316     } else {
    317       EXPECT_CALL(mobile_activator_, ChangeState(
    318           Eq(&cellular_network_),
    319           Eq(MobileActivator::PLAN_ACTIVATION_ERROR),
    320           _));
    321     }
    322     set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
    323     mobile_activator_.InvokeChangeState(&cellular_network_,
    324                                         kOTASPStates[i],
    325                                         error);
    326   }
    327 }
    328 
    329 TEST_F(MobileActivatorTest, OTASPStartAtStart) {
    330   set_network_activation_type(shill::kActivationTypeOTASP);
    331   EXPECT_CALL(mobile_activator_, HasRecentCellularPlanPayment())
    332       .WillOnce(Return(false));
    333   EXPECT_CALL(mobile_activator_,
    334               EvaluateCellularNetwork(Eq(&cellular_network_)));
    335   mobile_activator_.InvokeStartActivation();
    336   EXPECT_EQ(mobile_activator_.state(), MobileActivator::PLAN_ACTIVATION_START);
    337 }
    338 
    339 TEST_F(MobileActivatorTest, ReconnectOnDisconnectFromPaymentPortal) {
    340   // Most states either don't care if we're offline or expect to be offline at
    341   // some point.  For instance the OTASP states expect to go offline during
    342   // activation and eventually come back.  There are a few transitions states
    343   // like START_OTASP and DELAY_OTASP which don't really depend on the state of
    344   // the modem (offline or online) to work correctly.  A few places however,
    345   // like when we're displaying the portal care quite a bit about going
    346   // offline.  Lets test for those cases.
    347   std::string error_description;
    348   set_connection_state(shill::kStateFailure);
    349   set_network_activation_state(shill::kActivationStatePartiallyActivated);
    350   set_activator_state(MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING);
    351   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_RECONNECTING,
    352             mobile_activator_.InvokePickNextState(&cellular_network_,
    353                                                   &error_description));
    354   set_activator_state(MobileActivator::PLAN_ACTIVATION_SHOWING_PAYMENT);
    355   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_RECONNECTING,
    356             mobile_activator_.InvokePickNextState(&cellular_network_,
    357                                                   &error_description));
    358 }
    359 
    360 }  // namespace chromeos
    361