12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/mobile/mobile_activator.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/message_loop/message_loop.h" 84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/values.h" 9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h" 106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chromeos/network/network_connection_handler.h" 11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chromeos/network/network_handler.h" 12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chromeos/network/network_state.h" 136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chromeos/network/network_state_handler.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using std::string; 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using testing::_; 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using testing::Eq; 24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using testing::Invoke; 256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)using testing::Mock; 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using testing::Return; 276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)using testing::WithArgs; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kTestServicePath[] = "/a/service/path"; 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kNumOTASPStates = 3; 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)chromeos::MobileActivator::PlanActivationState kOTASPStates[kNumOTASPStates] = { 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chromeos::MobileActivator::PLAN_ACTIVATION_TRYING_OTASP, 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chromeos::MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION, 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chromeos::MobileActivator::PLAN_ACTIVATION_OTASP, 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos { 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TestMobileActivator : public MobileActivator { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) explicit TestMobileActivator(NetworkState* cellular_network) : 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cellular_network_(cellular_network) { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Provide reasonable defaults for basic things we're usually not testing. 496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ON_CALL(*this, ChangeState(_, _, _)) 506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) .WillByDefault(WithArgs<1>( 516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Invoke(this, &TestMobileActivator::set_state_for_test))); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~TestMobileActivator() {} 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 55424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) MOCK_METHOD3(RequestCellularActivation, 56424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) void(const NetworkState*, 57424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const base::Closure&, 58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const network_handler::ErrorCallback&)); 59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) MOCK_METHOD3(ChangeState, void(const NetworkState*, 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MobileActivator::PlanActivationState, 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string)); 626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) MOCK_METHOD0(GetDefaultNetwork, const NetworkState*()); 63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) MOCK_METHOD1(EvaluateCellularNetwork, void(const NetworkState*)); 64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) MOCK_METHOD0(SignalCellularPlanPayment, void(void)); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MOCK_METHOD0(StartOTASPTimer, void(void)); 66424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) MOCK_CONST_METHOD0(HasRecentCellularPlanPayment, bool(void)); 676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) MOCK_METHOD1(ConnectNetwork, void(const NetworkState*)); 686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) virtual const NetworkState* GetNetworkState(const std::string& service_path) { 706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return cellular_network_; 716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void InvokeStartActivation() { 746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) StartActivation(); 756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void InvokeHandlePortalLoaded(bool success) { 786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) HandlePortalLoaded(success); 796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void InvokeHandleSetTransactionStatus(bool success) { 826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) HandleSetTransactionStatus(success); 836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) PlanActivationState InvokePickNextState( 866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const NetworkState* network, 876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string* error_description) const { 886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return PickNextState(network, error_description); 896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) void InvokeChangeState(const NetworkState* network, 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MobileActivator::PlanActivationState new_state, 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string error_description) { 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MobileActivator::ChangeState(network, new_state, error_description); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void DCheckOnThread(const BrowserThread::ID id) const {} 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) NetworkState* cellular_network_; 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TestMobileActivator); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MobileActivatorTest : public testing::Test { 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MobileActivatorTest() 108424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) : cellular_network_(string(kTestServicePath)), 109424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) mobile_activator_(&cellular_network_) { 1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) cellular_network_.PropertyChanged(shill::kTypeProperty, 1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::StringValue(shill::kTypeCellular)); 112424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~MobileActivatorTest() {} 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected: 116424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) virtual void SetUp() { 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DBusThreadManager::Initialize(); 118424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) NetworkHandler::Initialize(); 119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) virtual void TearDown() { 121424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) NetworkHandler::Shutdown(); 122424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DBusThreadManager::Shutdown(); 123424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void set_activator_state(const MobileActivator::PlanActivationState state) { 1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.set_state_for_test(state); 1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void set_network_activation_type(const std::string& activation_type) { 1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) cellular_network_.activation_type_ = activation_type; 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) void set_network_activation_state(const std::string& activation_state) { 132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) cellular_network_.activation_state_ = activation_state; 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 134424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) void set_connection_state(const std::string& state) { 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) cellular_network_.visible_ = true; 136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) cellular_network_.connection_state_ = state; 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 139424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::MessageLoop message_loop_; 140424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) NetworkState cellular_network_; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TestMobileActivator mobile_activator_; 1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MobileActivatorTest); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)TEST_F(MobileActivatorTest, OTAHasNetworkConnection) { 1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Make sure if we have a network connection, the mobile activator does not 1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // connect to the network. 1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_CALL(mobile_activator_, GetDefaultNetwork()) 1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) .WillRepeatedly(Return(&cellular_network_)); 1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_CALL(mobile_activator_, ConnectNetwork(_)) 1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) .Times(0); 1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_connection_state(shill::kStatePortal); 1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_network_activation_type(shill::kActivationTypeOTA); 1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_network_activation_state(shill::kActivationStateNotActivated); 1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokeStartActivation(); 1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_EQ(mobile_activator_.state(), 1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING); 1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)TEST_F(MobileActivatorTest, OTANoNetworkConnection) { 1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Make sure if we don't have a network connection, the mobile activator 1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // connects to the network. 1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_CALL(mobile_activator_, GetDefaultNetwork()) 1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) .WillRepeatedly(Return(static_cast<NetworkState*>(NULL))); 1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_CALL(mobile_activator_, ConnectNetwork(&cellular_network_)); 1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_connection_state(shill::kStateIdle); 1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_network_activation_type(shill::kActivationTypeOTA); 1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_network_activation_state(shill::kActivationStateNotActivated); 1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokeStartActivation(); 1726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_EQ(mobile_activator_.state(), 1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) MobileActivator::PLAN_ACTIVATION_WAITING_FOR_CONNECTION); 1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)TEST_F(MobileActivatorTest, OTAActivationFlow) { 1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Once a network connection is available, the OTA flow should look like the 1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // following: 1796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // - Loading payment portal 1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // - Showing payment portal 1816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // - (User fills out payment portal and submits information) 1826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // - Activation complete 1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_CALL(mobile_activator_, GetDefaultNetwork()) 1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) .WillRepeatedly(Return(&cellular_network_)); 1856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_connection_state(shill::kStateOnline); 1866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_network_activation_type(shill::kActivationTypeOTA); 1876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_network_activation_state(shill::kActivationStateNotActivated); 1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokeStartActivation(); 1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_EQ(mobile_activator_.state(), 1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING); 1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokeHandlePortalLoaded(true); 1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_EQ(mobile_activator_.state(), 1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) MobileActivator::PLAN_ACTIVATION_SHOWING_PAYMENT); 1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokeHandleSetTransactionStatus(true); 1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_EQ(mobile_activator_.state(), MobileActivator::PLAN_ACTIVATION_DONE); 1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)TEST_F(MobileActivatorTest, OTASPBasicFlowForNewDevices) { 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // In a new device, we aren't connected to Verizon, we start at START 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // because we haven't paid Verizon (ever), and the modem isn't even partially 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // activated. 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string error_description; 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_activator_state(MobileActivator::PLAN_ACTIVATION_START); 20468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) set_connection_state(shill::kStateIdle); 2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_network_activation_type(shill::kActivationTypeOTASP); 20668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) set_network_activation_state(shill::kActivationStateNotActivated); 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION, 2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokePickNextState(&cellular_network_, 2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &error_description)); 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Now behave as if ChangeState() has initiated an activation. 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_activator_state(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION); 21268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) set_network_activation_state(shill::kActivationStateActivating); 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We'll sit in this state while we wait for the OTASP to finish. 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION, 2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokePickNextState(&cellular_network_, 2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &error_description)); 21768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) set_network_activation_state(shill::kActivationStatePartiallyActivated); 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We'll sit in this state until we go online as well. 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION, 2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokePickNextState(&cellular_network_, 2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &error_description)); 22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) set_connection_state(shill::kStatePortal); 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // After we go online, we go back to START, which acts as a jumping off 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // point for the two types of initial OTASP. 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_START, 2266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokePickNextState(&cellular_network_, 2276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &error_description)); 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_activator_state(MobileActivator::PLAN_ACTIVATION_START); 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP, 2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokePickNextState(&cellular_network_, 2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &error_description)); 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Very similar things happen while we're trying OTASP. 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_activator_state(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP); 23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) set_network_activation_state(shill::kActivationStateActivating); 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP, 2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokePickNextState(&cellular_network_, 2376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &error_description)); 23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) set_network_activation_state(shill::kActivationStatePartiallyActivated); 23968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) set_connection_state(shill::kStatePortal); 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // And when we come back online again and aren't activating, load the portal. 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING, 2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokePickNextState(&cellular_network_, 2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &error_description)); 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The JS drives us through the payment portal. 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_activator_state(MobileActivator::PLAN_ACTIVATION_SHOWING_PAYMENT); 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The JS also calls us to signal that the portal is done. This triggers us 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to start our final OTASP via the aptly named StartOTASP(). 248424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) EXPECT_CALL(mobile_activator_, SignalCellularPlanPayment()); 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_CALL(mobile_activator_, 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ChangeState(Eq(&cellular_network_), 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Eq(MobileActivator::PLAN_ACTIVATION_START_OTASP), 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _)); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_CALL(mobile_activator_, 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EvaluateCellularNetwork(Eq(&cellular_network_))); 2556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokeHandleSetTransactionStatus(true); 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Evaluate state will defer to PickNextState to select what to do now that 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // we're in START_ACTIVATION. PickNextState should decide to start a final 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // OTASP. 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_activator_state(MobileActivator::PLAN_ACTIVATION_START_OTASP); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_OTASP, 2616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokePickNextState(&cellular_network_, 2626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &error_description)); 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Similarly to TRYING_OTASP and INITIATING_OTASP above... 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_activator_state(MobileActivator::PLAN_ACTIVATION_OTASP); 26568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) set_network_activation_state(shill::kActivationStateActivating); 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_OTASP, 2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokePickNextState(&cellular_network_, 2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &error_description)); 26968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) set_network_activation_state(shill::kActivationStateActivated); 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_DONE, 2716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokePickNextState(&cellular_network_, 2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &error_description)); 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// A fake for MobileActivator::RequestCellularActivation that always succeeds. 276424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void FakeRequestCellularActivationSuccess( 277424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const NetworkState* network, 278424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const base::Closure& success_callback, 279424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const network_handler::ErrorCallback& error_callback) { 280424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) success_callback.Run(); 281424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 282424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 283424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// A fake for MobileActivator::RequestCellularActivation that always fails. 284424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void FakeRequestCellularActivationFailure( 285424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const NetworkState* network, 286424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const base::Closure& success_callback, 287424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const network_handler::ErrorCallback& error_callback) { 288424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) scoped_ptr<base::DictionaryValue> value; 289424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) error_callback.Run("", value.Pass()); 290424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 291424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(MobileActivatorTest, OTASPScheduling) { 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string error; 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < kNumOTASPStates; ++i) { 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // When activation works, we start a timer to watch for success. 296424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) EXPECT_CALL(mobile_activator_, RequestCellularActivation(_, _, _)) 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) .Times(1) 298424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) .WillOnce(Invoke(FakeRequestCellularActivationSuccess)); 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_CALL(mobile_activator_, StartOTASPTimer()) 300424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) .Times(1); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_activator_state(MobileActivator::PLAN_ACTIVATION_START); 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mobile_activator_.InvokeChangeState(&cellular_network_, 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kOTASPStates[i], 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error); 305424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // When activation fails, it's an error, unless we're trying for the final 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // OTASP, in which case we try again via DELAY_OTASP. 308424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) EXPECT_CALL(mobile_activator_, RequestCellularActivation(_, _, _)) 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) .Times(1) 310424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) .WillOnce(Invoke(FakeRequestCellularActivationFailure)); 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (kOTASPStates[i] == MobileActivator::PLAN_ACTIVATION_OTASP) { 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_CALL(mobile_activator_, ChangeState( 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Eq(&cellular_network_), 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Eq(MobileActivator::PLAN_ACTIVATION_DELAY_OTASP), 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _)); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_CALL(mobile_activator_, ChangeState( 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Eq(&cellular_network_), 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Eq(MobileActivator::PLAN_ACTIVATION_ERROR), 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _)); 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_activator_state(MobileActivator::PLAN_ACTIVATION_START); 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mobile_activator_.InvokeChangeState(&cellular_network_, 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kOTASPStates[i], 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error); 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)TEST_F(MobileActivatorTest, OTASPStartAtStart) { 3306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_network_activation_type(shill::kActivationTypeOTASP); 3316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_CALL(mobile_activator_, HasRecentCellularPlanPayment()) 3326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) .WillOnce(Return(false)); 3336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_CALL(mobile_activator_, 3346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EvaluateCellularNetwork(Eq(&cellular_network_))); 3356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokeStartActivation(); 3366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_EQ(mobile_activator_.state(), MobileActivator::PLAN_ACTIVATION_START); 3376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(MobileActivatorTest, ReconnectOnDisconnectFromPaymentPortal) { 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Most states either don't care if we're offline or expect to be offline at 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // some point. For instance the OTASP states expect to go offline during 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // activation and eventually come back. There are a few transitions states 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // like START_OTASP and DELAY_OTASP which don't really depend on the state of 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the modem (offline or online) to work correctly. A few places however, 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // like when we're displaying the portal care quite a bit about going 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // offline. Lets test for those cases. 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string error_description; 34868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) set_connection_state(shill::kStateFailure); 34968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) set_network_activation_state(shill::kActivationStatePartiallyActivated); 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_activator_state(MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING); 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_RECONNECTING, 3526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokePickNextState(&cellular_network_, 3536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &error_description)); 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_activator_state(MobileActivator::PLAN_ACTIVATION_SHOWING_PAYMENT); 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_RECONNECTING, 3566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mobile_activator_.InvokePickNextState(&cellular_network_, 3576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &error_description)); 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace chromeos 361