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_handler.h"
     11 #include "chromeos/network/network_state.h"
     12 #include "content/public/browser/browser_thread.h"
     13 #include "testing/gmock/include/gmock/gmock.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 #include "third_party/cros_system_api/dbus/service_constants.h"
     16 
     17 using std::string;
     18 
     19 using content::BrowserThread;
     20 using testing::_;
     21 using testing::Eq;
     22 using testing::Invoke;
     23 using testing::Return;
     24 
     25 namespace {
     26 
     27 const char kTestServicePath[] = "/a/service/path";
     28 
     29 const size_t kNumOTASPStates = 3;
     30 
     31 chromeos::MobileActivator::PlanActivationState kOTASPStates[kNumOTASPStates] = {
     32   chromeos::MobileActivator::PLAN_ACTIVATION_TRYING_OTASP,
     33   chromeos::MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
     34   chromeos::MobileActivator::PLAN_ACTIVATION_OTASP,
     35 };
     36 
     37 }  // namespace
     38 namespace chromeos {
     39 
     40 class TestMobileActivator : public MobileActivator {
     41  public:
     42   explicit TestMobileActivator(NetworkState* cellular_network) :
     43         cellular_network_(cellular_network) {
     44     // Provide reasonable defaults for basic things we're usually not testing.
     45     ON_CALL(*this, DCheckOnThread(_))
     46         .WillByDefault(Return());
     47     ON_CALL(*this, GetNetworkState(_))
     48         .WillByDefault(Return(cellular_network_));
     49   }
     50   virtual ~TestMobileActivator() {}
     51 
     52   MOCK_METHOD3(RequestCellularActivation,
     53                void(const NetworkState*,
     54                     const base::Closure&,
     55                     const network_handler::ErrorCallback&));
     56   MOCK_METHOD3(ChangeState, void(const NetworkState*,
     57                                  MobileActivator::PlanActivationState,
     58                                  std::string));
     59   MOCK_METHOD1(GetNetworkState, const NetworkState*(const std::string&));
     60   MOCK_METHOD1(EvaluateCellularNetwork, void(const NetworkState*));
     61   MOCK_METHOD0(SignalCellularPlanPayment, void(void));
     62   MOCK_METHOD0(StartOTASPTimer, void(void));
     63   MOCK_CONST_METHOD0(HasRecentCellularPlanPayment, bool(void));
     64 
     65   void InvokeChangeState(const NetworkState* network,
     66                          MobileActivator::PlanActivationState new_state,
     67                          std::string error_description) {
     68     MobileActivator::ChangeState(network, new_state, error_description);
     69   }
     70 
     71  private:
     72   MOCK_CONST_METHOD1(DCheckOnThread, void(const BrowserThread::ID id));
     73 
     74   NetworkState* cellular_network_;
     75 
     76   DISALLOW_COPY_AND_ASSIGN(TestMobileActivator);
     77 };
     78 
     79 class MobileActivatorTest : public testing::Test {
     80  public:
     81   MobileActivatorTest()
     82       : cellular_network_(string(kTestServicePath)),
     83         mobile_activator_(&cellular_network_) {
     84   }
     85   virtual ~MobileActivatorTest() {}
     86 
     87  protected:
     88   virtual void SetUp() {
     89     DBusThreadManager::InitializeWithStub();
     90     NetworkHandler::Initialize();
     91   }
     92   virtual void TearDown() {
     93     NetworkHandler::Shutdown();
     94     DBusThreadManager::Shutdown();
     95   }
     96 
     97   void set_activator_state(const MobileActivator::PlanActivationState state) {
     98     mobile_activator_.state_ = state;
     99   }
    100   void set_network_activation_state(const std::string& activation_state) {
    101     cellular_network_.activation_state_ = activation_state;
    102   }
    103   void set_connection_state(const std::string& state) {
    104     cellular_network_.visible_ = true;
    105     cellular_network_.connection_state_ = state;
    106   }
    107 
    108   base::MessageLoop message_loop_;
    109   NetworkState cellular_network_;
    110   TestMobileActivator mobile_activator_;
    111  private:
    112   DISALLOW_COPY_AND_ASSIGN(MobileActivatorTest);
    113 };
    114 
    115 TEST_F(MobileActivatorTest, BasicFlowForNewDevices) {
    116   // In a new device, we aren't connected to Verizon, we start at START
    117   // because we haven't paid Verizon (ever), and the modem isn't even partially
    118   // activated.
    119   std::string error_description;
    120   set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
    121   set_connection_state(shill::kStateIdle);
    122   set_network_activation_state(shill::kActivationStateNotActivated);
    123   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
    124             mobile_activator_.PickNextState(&cellular_network_,
    125                                             &error_description));
    126   // Now behave as if ChangeState() has initiated an activation.
    127   set_activator_state(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION);
    128   set_network_activation_state(shill::kActivationStateActivating);
    129   // We'll sit in this state while we wait for the OTASP to finish.
    130   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
    131             mobile_activator_.PickNextState(&cellular_network_,
    132                                             &error_description));
    133   set_network_activation_state(shill::kActivationStatePartiallyActivated);
    134   // We'll sit in this state until we go online as well.
    135   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
    136             mobile_activator_.PickNextState(&cellular_network_,
    137                                             &error_description));
    138   set_connection_state(shill::kStatePortal);
    139   // After we go online, we go back to START, which acts as a jumping off
    140   // point for the two types of initial OTASP.
    141   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_START,
    142             mobile_activator_.PickNextState(&cellular_network_,
    143                                             &error_description));
    144   set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
    145   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP,
    146             mobile_activator_.PickNextState(&cellular_network_,
    147                                             &error_description));
    148   // Very similar things happen while we're trying OTASP.
    149   set_activator_state(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP);
    150   set_network_activation_state(shill::kActivationStateActivating);
    151   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP,
    152             mobile_activator_.PickNextState(&cellular_network_,
    153                                             &error_description));
    154   set_network_activation_state(shill::kActivationStatePartiallyActivated);
    155   set_connection_state(shill::kStatePortal);
    156   // And when we come back online again and aren't activating, load the portal.
    157   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING,
    158             mobile_activator_.PickNextState(&cellular_network_,
    159                                             &error_description));
    160   // The JS drives us through the payment portal.
    161   set_activator_state(MobileActivator::PLAN_ACTIVATION_SHOWING_PAYMENT);
    162   // The JS also calls us to signal that the portal is done.  This triggers us
    163   // to start our final OTASP via the aptly named StartOTASP().
    164   EXPECT_CALL(mobile_activator_, SignalCellularPlanPayment());
    165   EXPECT_CALL(mobile_activator_,
    166               ChangeState(Eq(&cellular_network_),
    167                           Eq(MobileActivator::PLAN_ACTIVATION_START_OTASP),
    168                           _));
    169   EXPECT_CALL(mobile_activator_,
    170               EvaluateCellularNetwork(Eq(&cellular_network_)));
    171   mobile_activator_.HandleSetTransactionStatus(true);
    172   // Evaluate state will defer to PickNextState to select what to do now that
    173   // we're in START_ACTIVATION.  PickNextState should decide to start a final
    174   // OTASP.
    175   set_activator_state(MobileActivator::PLAN_ACTIVATION_START_OTASP);
    176   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_OTASP,
    177             mobile_activator_.PickNextState(&cellular_network_,
    178                                             &error_description));
    179   // Similarly to TRYING_OTASP and INITIATING_OTASP above...
    180   set_activator_state(MobileActivator::PLAN_ACTIVATION_OTASP);
    181   set_network_activation_state(shill::kActivationStateActivating);
    182   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_OTASP,
    183             mobile_activator_.PickNextState(&cellular_network_,
    184                                             &error_description));
    185   set_network_activation_state(shill::kActivationStateActivated);
    186   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_DONE,
    187             mobile_activator_.PickNextState(&cellular_network_,
    188                                             &error_description));
    189 }
    190 
    191 // A fake for MobileActivator::RequestCellularActivation that always succeeds.
    192 void FakeRequestCellularActivationSuccess(
    193     const NetworkState* network,
    194     const base::Closure& success_callback,
    195     const network_handler::ErrorCallback& error_callback) {
    196   success_callback.Run();
    197 }
    198 
    199 // A fake for MobileActivator::RequestCellularActivation that always fails.
    200 void FakeRequestCellularActivationFailure(
    201     const NetworkState* network,
    202     const base::Closure& success_callback,
    203     const network_handler::ErrorCallback& error_callback) {
    204   scoped_ptr<base::DictionaryValue> value;
    205   error_callback.Run("", value.Pass());
    206 }
    207 
    208 TEST_F(MobileActivatorTest, OTASPScheduling) {
    209   const std::string error;
    210   for (size_t i = 0; i < kNumOTASPStates; ++i) {
    211     // When activation works, we start a timer to watch for success.
    212     EXPECT_CALL(mobile_activator_, RequestCellularActivation(_, _, _))
    213         .Times(1)
    214         .WillOnce(Invoke(FakeRequestCellularActivationSuccess));
    215     EXPECT_CALL(mobile_activator_, StartOTASPTimer())
    216          .Times(1);
    217     set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
    218     mobile_activator_.InvokeChangeState(&cellular_network_,
    219                                         kOTASPStates[i],
    220                                         error);
    221 
    222     // When activation fails, it's an error, unless we're trying for the final
    223     // OTASP, in which case we try again via DELAY_OTASP.
    224     EXPECT_CALL(mobile_activator_, RequestCellularActivation(_, _, _))
    225         .Times(1)
    226         .WillOnce(Invoke(FakeRequestCellularActivationFailure));
    227     if (kOTASPStates[i] == MobileActivator::PLAN_ACTIVATION_OTASP) {
    228       EXPECT_CALL(mobile_activator_, ChangeState(
    229           Eq(&cellular_network_),
    230           Eq(MobileActivator::PLAN_ACTIVATION_DELAY_OTASP),
    231           _));
    232     } else {
    233       EXPECT_CALL(mobile_activator_, ChangeState(
    234           Eq(&cellular_network_),
    235           Eq(MobileActivator::PLAN_ACTIVATION_ERROR),
    236           _));
    237     }
    238     set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
    239     mobile_activator_.InvokeChangeState(&cellular_network_,
    240                                         kOTASPStates[i],
    241                                         error);
    242   }
    243 }
    244 
    245 TEST_F(MobileActivatorTest, ReconnectOnDisconnectFromPaymentPortal) {
    246   // Most states either don't care if we're offline or expect to be offline at
    247   // some point.  For instance the OTASP states expect to go offline during
    248   // activation and eventually come back.  There are a few transitions states
    249   // like START_OTASP and DELAY_OTASP which don't really depend on the state of
    250   // the modem (offline or online) to work correctly.  A few places however,
    251   // like when we're displaying the portal care quite a bit about going
    252   // offline.  Lets test for those cases.
    253   std::string error_description;
    254   set_connection_state(shill::kStateFailure);
    255   set_network_activation_state(shill::kActivationStatePartiallyActivated);
    256   set_activator_state(MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING);
    257   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_RECONNECTING,
    258             mobile_activator_.PickNextState(&cellular_network_,
    259                                             &error_description));
    260   set_activator_state(MobileActivator::PLAN_ACTIVATION_SHOWING_PAYMENT);
    261   EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_RECONNECTING,
    262             mobile_activator_.PickNextState(&cellular_network_,
    263                                             &error_description));
    264 }
    265 
    266 TEST_F(MobileActivatorTest, StartAtStart) {
    267   EXPECT_CALL(mobile_activator_, HasRecentCellularPlanPayment())
    268       .WillOnce(Return(false));
    269   EXPECT_CALL(mobile_activator_,
    270               EvaluateCellularNetwork(Eq(&cellular_network_)));
    271   mobile_activator_.StartActivation();
    272   EXPECT_EQ(mobile_activator_.state(), MobileActivator::PLAN_ACTIVATION_START);
    273 }
    274 
    275 }  // namespace chromeos
    276