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