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.
5 #include "chrome/browser/chromeos/mobile/mobile_activator.h"
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"
21 using content::BrowserThread
;
24 using testing::Invoke
;
26 using testing::Return
;
27 using testing::WithArgs
;
31 const char kTestServicePath
[] = "/a/service/path";
33 const size_t kNumOTASPStates
= 3;
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
,
44 class TestMobileActivator
: public MobileActivator
{
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
)));
53 virtual ~TestMobileActivator() {}
55 MOCK_METHOD3(RequestCellularActivation
,
56 void(const NetworkState
*,
58 const network_handler::ErrorCallback
&));
59 MOCK_METHOD3(ChangeState
, void(const NetworkState
*,
60 MobileActivator::PlanActivationState
,
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
*));
69 virtual const NetworkState
* GetNetworkState(const std::string
& service_path
) {
70 return cellular_network_
;
73 void InvokeStartActivation() {
77 void InvokeHandlePortalLoaded(bool success
) {
78 HandlePortalLoaded(success
);
81 void InvokeHandleSetTransactionStatus(bool success
) {
82 HandleSetTransactionStatus(success
);
85 PlanActivationState
InvokePickNextState(
86 const NetworkState
* network
,
87 std::string
* error_description
) const {
88 return PickNextState(network
, error_description
);
91 void InvokeChangeState(const NetworkState
* network
,
92 MobileActivator::PlanActivationState new_state
,
93 std::string error_description
) {
94 MobileActivator::ChangeState(network
, new_state
, error_description
);
98 void DCheckOnThread(const BrowserThread::ID id
) const {}
100 NetworkState
* cellular_network_
;
102 DISALLOW_COPY_AND_ASSIGN(TestMobileActivator
);
105 class MobileActivatorTest
: public testing::Test
{
107 MobileActivatorTest()
108 : cellular_network_(string(kTestServicePath
)),
109 mobile_activator_(&cellular_network_
) {
110 cellular_network_
.PropertyChanged(shill::kTypeProperty
,
111 base::StringValue(shill::kTypeCellular
));
113 ~MobileActivatorTest() override
{}
116 void SetUp() override
{
117 DBusThreadManager::Initialize();
118 NetworkHandler::Initialize();
120 void TearDown() override
{
121 NetworkHandler::Shutdown();
122 DBusThreadManager::Shutdown();
125 void set_activator_state(const MobileActivator::PlanActivationState state
) {
126 mobile_activator_
.set_state_for_test(state
);
128 void set_network_activation_type(const std::string
& activation_type
) {
129 cellular_network_
.activation_type_
= activation_type
;
131 void set_network_activation_state(const std::string
& activation_state
) {
132 cellular_network_
.activation_state_
= activation_state
;
134 void set_connection_state(const std::string
& state
) {
135 cellular_network_
.visible_
= true;
136 cellular_network_
.connection_state_
= state
;
139 base::MessageLoop message_loop_
;
140 NetworkState cellular_network_
;
141 TestMobileActivator mobile_activator_
;
144 DISALLOW_COPY_AND_ASSIGN(MobileActivatorTest
);
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(_
))
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
);
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
);
176 TEST_F(MobileActivatorTest
, OTAActivationFlow
) {
177 // Once a network connection is available, the OTA flow should look like the
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
);
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
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
),
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
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
));
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();
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());
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(_
, _
, _
))
298 .WillOnce(Invoke(FakeRequestCellularActivationSuccess
));
299 EXPECT_CALL(mobile_activator_
, StartOTASPTimer())
301 set_activator_state(MobileActivator::PLAN_ACTIVATION_START
);
302 mobile_activator_
.InvokeChangeState(&cellular_network_
,
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(_
, _
, _
))
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
),
317 EXPECT_CALL(mobile_activator_
, ChangeState(
318 Eq(&cellular_network_
),
319 Eq(MobileActivator::PLAN_ACTIVATION_ERROR
),
322 set_activator_state(MobileActivator::PLAN_ACTIVATION_START
);
323 mobile_activator_
.InvokeChangeState(&cellular_network_
,
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
);
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
));
360 } // namespace chromeos