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