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 <algorithm>
      8 #include <map>
      9 #include <string>
     10 
     11 #include "ash/system/chromeos/network/network_connect.h"
     12 #include "base/bind.h"
     13 #include "base/bind_helpers.h"
     14 #include "base/files/file_util.h"
     15 #include "base/json/json_reader.h"
     16 #include "base/location.h"
     17 #include "base/logging.h"
     18 #include "base/memory/ref_counted_memory.h"
     19 #include "base/message_loop/message_loop.h"
     20 #include "base/metrics/histogram.h"
     21 #include "base/observer_list_threadsafe.h"
     22 #include "base/prefs/pref_service.h"
     23 #include "base/strings/string_piece.h"
     24 #include "base/strings/string_util.h"
     25 #include "base/strings/utf_string_conversions.h"
     26 #include "base/timer/timer.h"
     27 #include "base/values.h"
     28 #include "chrome/browser/browser_process.h"
     29 #include "chrome/common/pref_names.h"
     30 #include "chromeos/network/device_state.h"
     31 #include "chromeos/network/network_activation_handler.h"
     32 #include "chromeos/network/network_configuration_handler.h"
     33 #include "chromeos/network/network_connection_handler.h"
     34 #include "chromeos/network/network_event_log.h"
     35 #include "chromeos/network/network_handler_callbacks.h"
     36 #include "chromeos/network/network_state.h"
     37 #include "chromeos/network/network_state_handler.h"
     38 #include "content/public/browser/browser_thread.h"
     39 #include "third_party/cros_system_api/dbus/service_constants.h"
     40 
     41 using content::BrowserThread;
     42 
     43 namespace {
     44 
     45 // Cellular configuration file path.
     46 const char kCellularConfigPath[] =
     47     "/usr/share/chromeos-assets/mobile/mobile_config.json";
     48 
     49 // Cellular config file field names.
     50 const char kVersionField[] = "version";
     51 const char kErrorsField[] = "errors";
     52 
     53 // Number of times we'll try an OTASP before failing the activation process.
     54 const int kMaxOTASPTries = 3;
     55 // Number of times we will retry to reconnect and reload payment portal page.
     56 const int kMaxPortalReconnectCount = 2;
     57 // Time between connection attempts when forcing a reconnect.
     58 const int kReconnectDelayMS = 3000;
     59 // Retry delay after failed OTASP attempt.
     60 const int kOTASPRetryDelay = 40000;
     61 // Maximum amount of time we'll wait for a service to reconnect.
     62 const int kMaxReconnectTime = 30000;
     63 
     64 // Error codes matching codes defined in the cellular config file.
     65 const char kErrorDefault[] = "default";
     66 const char kErrorBadConnectionPartial[] = "bad_connection_partial";
     67 const char kErrorBadConnectionActivated[] = "bad_connection_activated";
     68 const char kErrorRoamingOnConnection[] = "roaming_connection";
     69 const char kErrorNoEVDO[] = "no_evdo";
     70 const char kErrorRoamingActivation[] = "roaming_activation";
     71 const char kErrorRoamingPartiallyActivated[] = "roaming_partially_activated";
     72 const char kErrorNoService[] = "no_service";
     73 const char kErrorDisabled[] = "disabled";
     74 const char kErrorNoDevice[] = "no_device";
     75 const char kFailedPaymentError[] = "failed_payment";
     76 const char kFailedConnectivity[] = "connectivity";
     77 
     78 // Returns true if the device follows the simple activation flow.
     79 bool IsSimpleActivationFlow(const chromeos::NetworkState* network) {
     80   return (network->activation_type() == shill::kActivationTypeNonCellular ||
     81           network->activation_type() == shill::kActivationTypeOTA);
     82 }
     83 
     84 }  // namespace
     85 
     86 namespace chromeos {
     87 
     88 ////////////////////////////////////////////////////////////////////////////////
     89 //
     90 // CellularConfigDocument
     91 //
     92 ////////////////////////////////////////////////////////////////////////////////
     93 CellularConfigDocument::CellularConfigDocument() {}
     94 
     95 std::string CellularConfigDocument::GetErrorMessage(const std::string& code) {
     96   base::AutoLock create(config_lock_);
     97   ErrorMap::iterator iter = error_map_.find(code);
     98   if (iter == error_map_.end())
     99     return code;
    100   return iter->second;
    101 }
    102 
    103 void CellularConfigDocument::LoadCellularConfigFile() {
    104   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
    105   // Load partner customization startup manifest if it is available.
    106   base::FilePath config_path(kCellularConfigPath);
    107   if (!base::PathExists(config_path))
    108     return;
    109 
    110   if (LoadFromFile(config_path))
    111     DVLOG(1) << "Cellular config file loaded: " << kCellularConfigPath;
    112   else
    113     LOG(ERROR) << "Error loading cellular config file: " << kCellularConfigPath;
    114 }
    115 
    116 CellularConfigDocument::~CellularConfigDocument() {}
    117 
    118 void CellularConfigDocument::SetErrorMap(
    119     const ErrorMap& map) {
    120   base::AutoLock create(config_lock_);
    121   error_map_.clear();
    122   error_map_.insert(map.begin(), map.end());
    123 }
    124 
    125 bool CellularConfigDocument::LoadFromFile(const base::FilePath& config_path) {
    126   std::string config;
    127   if (!base::ReadFileToString(config_path, &config))
    128     return false;
    129 
    130   scoped_ptr<base::Value> root(
    131       base::JSONReader::Read(config, base::JSON_ALLOW_TRAILING_COMMAS));
    132   DCHECK(root.get() != NULL);
    133   if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY) {
    134     LOG(WARNING) << "Bad cellular config file";
    135     return false;
    136   }
    137 
    138   base::DictionaryValue* root_dict =
    139       static_cast<base::DictionaryValue*>(root.get());
    140   if (!root_dict->GetString(kVersionField, &version_)) {
    141     LOG(WARNING) << "Cellular config file missing version";
    142     return false;
    143   }
    144   ErrorMap error_map;
    145   base::DictionaryValue* errors = NULL;
    146   if (!root_dict->GetDictionary(kErrorsField, &errors))
    147     return false;
    148   for (base::DictionaryValue::Iterator it(*errors);
    149       !it.IsAtEnd(); it.Advance()) {
    150     std::string value;
    151     if (!it.value().GetAsString(&value)) {
    152       LOG(WARNING) << "Bad cellular config error value";
    153       return false;
    154     }
    155     error_map.insert(ErrorMap::value_type(it.key(), value));
    156   }
    157   SetErrorMap(error_map);
    158   return true;
    159 }
    160 
    161 ////////////////////////////////////////////////////////////////////////////////
    162 //
    163 // MobileActivator
    164 //
    165 ////////////////////////////////////////////////////////////////////////////////
    166 MobileActivator::MobileActivator()
    167     : cellular_config_(new CellularConfigDocument()),
    168       state_(PLAN_ACTIVATION_PAGE_LOADING),
    169       reenable_cert_check_(false),
    170       terminated_(true),
    171       pending_activation_request_(false),
    172       connection_retry_count_(0),
    173       initial_OTASP_attempts_(0),
    174       trying_OTASP_attempts_(0),
    175       final_OTASP_attempts_(0),
    176       payment_reconnect_count_(0),
    177       weak_ptr_factory_(this) {
    178 }
    179 
    180 MobileActivator::~MobileActivator() {
    181   TerminateActivation();
    182 }
    183 
    184 MobileActivator* MobileActivator::GetInstance() {
    185   return Singleton<MobileActivator>::get();
    186 }
    187 
    188 void MobileActivator::TerminateActivation() {
    189   state_duration_timer_.Stop();
    190   continue_reconnect_timer_.Stop();
    191   reconnect_timeout_timer_.Stop();
    192 
    193   if (NetworkHandler::IsInitialized()) {
    194     NetworkHandler::Get()->network_state_handler()->
    195         RemoveObserver(this, FROM_HERE);
    196   }
    197   ReEnableCertRevocationChecking();
    198   meid_.clear();
    199   iccid_.clear();
    200   service_path_.clear();
    201   device_path_.clear();
    202   state_ = PLAN_ACTIVATION_PAGE_LOADING;
    203   reenable_cert_check_ = false;
    204   terminated_ = true;
    205   // Release the previous cellular config and setup a new empty one.
    206   cellular_config_ = new CellularConfigDocument();
    207 }
    208 
    209 void MobileActivator::DefaultNetworkChanged(const NetworkState* network) {
    210   RefreshCellularNetworks();
    211 }
    212 
    213 void MobileActivator::NetworkPropertiesUpdated(const NetworkState* network) {
    214   if (state_ == PLAN_ACTIVATION_PAGE_LOADING)
    215     return;
    216 
    217   if (!network || network->type() != shill::kTypeCellular)
    218     return;
    219 
    220   const DeviceState* device = NetworkHandler::Get()->network_state_handler()->
    221       GetDeviceState(network->device_path());
    222   if (!device) {
    223     LOG(ERROR) << "Cellular device can't be found: " << network->device_path();
    224     return;
    225   }
    226   if (network->device_path() != device_path_) {
    227     LOG(WARNING) << "Ignoring property update for cellular service "
    228                  << network->path()
    229                  << " on unknown device " << network->device_path()
    230                  << " (Stored device path = " << device_path_ << ")";
    231     return;
    232   }
    233 
    234   // A modem reset leads to a new service path. Since we have verified that we
    235   // are a cellular service on a still valid stored device path, update it.
    236   service_path_ = network->path();
    237 
    238   EvaluateCellularNetwork(network);
    239 }
    240 
    241 void MobileActivator::AddObserver(MobileActivator::Observer* observer) {
    242   DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::UI));
    243   observers_.AddObserver(observer);
    244 }
    245 
    246 void MobileActivator::RemoveObserver(MobileActivator::Observer* observer) {
    247   DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::UI));
    248   observers_.RemoveObserver(observer);
    249 }
    250 
    251 void MobileActivator::InitiateActivation(const std::string& service_path) {
    252   DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::UI));
    253   const NetworkState* network =  GetNetworkState(service_path);
    254   if (!network) {
    255     LOG(WARNING) << "Cellular service can't be found: " << service_path;
    256     return;
    257   }
    258   const DeviceState* device = NetworkHandler::Get()->network_state_handler()->
    259       GetDeviceState(network->device_path());
    260   if (!device) {
    261     LOG(ERROR) << "Cellular device can't be found: " << network->device_path();
    262     return;
    263   }
    264 
    265   terminated_ = false;
    266   meid_ = device->meid();
    267   iccid_ = device->iccid();
    268   service_path_ = service_path;
    269   device_path_ = network->device_path();
    270 
    271   ChangeState(network, PLAN_ACTIVATION_PAGE_LOADING, "");
    272 
    273   BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE,
    274       base::Bind(&CellularConfigDocument::LoadCellularConfigFile,
    275                  cellular_config_.get()),
    276       base::Bind(&MobileActivator::ContinueActivation, AsWeakPtr()));
    277 }
    278 
    279 void MobileActivator::ContinueActivation() {
    280   NetworkHandler::Get()->network_configuration_handler()->GetProperties(
    281       service_path_,
    282       base::Bind(&MobileActivator::GetPropertiesAndContinueActivation,
    283                  weak_ptr_factory_.GetWeakPtr()),
    284       base::Bind(&MobileActivator::GetPropertiesFailure,
    285                  weak_ptr_factory_.GetWeakPtr()));
    286 }
    287 
    288 void MobileActivator::GetPropertiesAndContinueActivation(
    289     const std::string& service_path,
    290     const base::DictionaryValue& properties) {
    291   if (service_path != service_path_) {
    292     NET_LOG_EVENT("MobileActivator::GetProperties received for stale network",
    293                   service_path);
    294     return;  // Edge case; abort.
    295   }
    296   const base::DictionaryValue* payment_dict;
    297   std::string usage_url, payment_url;
    298   if (!properties.GetStringWithoutPathExpansion(
    299           shill::kUsageURLProperty, &usage_url) ||
    300       !properties.GetDictionaryWithoutPathExpansion(
    301           shill::kPaymentPortalProperty, &payment_dict) ||
    302       !payment_dict->GetStringWithoutPathExpansion(
    303           shill::kPaymentPortalURL, &payment_url)) {
    304     NET_LOG_ERROR("MobileActivator missing properties", service_path_);
    305     return;
    306   }
    307 
    308   if (payment_url.empty() && usage_url.empty())
    309     return;
    310 
    311   DisableCertRevocationChecking();
    312 
    313   // We want shill to connect us after activations, so enable autoconnect.
    314   base::DictionaryValue auto_connect_property;
    315   auto_connect_property.SetBoolean(shill::kAutoConnectProperty, true);
    316   NetworkHandler::Get()->network_configuration_handler()->SetProperties(
    317       service_path_,
    318       auto_connect_property,
    319       base::Bind(&base::DoNothing),
    320       network_handler::ErrorCallback());
    321   StartActivation();
    322 }
    323 
    324 void MobileActivator::GetPropertiesFailure(
    325     const std::string& error_name,
    326     scoped_ptr<base::DictionaryValue> error_data) {
    327   NET_LOG_ERROR("MobileActivator GetProperties Failed: " + error_name,
    328                 service_path_);
    329 }
    330 
    331 void MobileActivator::OnSetTransactionStatus(bool success) {
    332   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    333       base::Bind(&MobileActivator::HandleSetTransactionStatus,
    334                  AsWeakPtr(), success));
    335 }
    336 
    337 void MobileActivator::HandleSetTransactionStatus(bool success) {
    338   // The payment is received, try to reconnect and check the status all over
    339   // again.
    340   if (success && state_ == PLAN_ACTIVATION_SHOWING_PAYMENT) {
    341     SignalCellularPlanPayment();
    342     UMA_HISTOGRAM_COUNTS("Cellular.PaymentReceived", 1);
    343     const NetworkState* network = GetNetworkState(service_path_);
    344     if (network && IsSimpleActivationFlow(network)) {
    345       state_ = PLAN_ACTIVATION_DONE;
    346       NetworkHandler::Get()->network_activation_handler()->
    347           CompleteActivation(network->path(),
    348                              base::Bind(&base::DoNothing),
    349                              network_handler::ErrorCallback());
    350     } else {
    351       StartOTASP();
    352     }
    353   } else {
    354     UMA_HISTOGRAM_COUNTS("Cellular.PaymentFailed", 1);
    355   }
    356 }
    357 
    358 void MobileActivator::OnPortalLoaded(bool success) {
    359   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    360       base::Bind(&MobileActivator::HandlePortalLoaded,
    361                  AsWeakPtr(), success));
    362 }
    363 
    364 void MobileActivator::HandlePortalLoaded(bool success) {
    365   const NetworkState* network = GetNetworkState(service_path_);
    366   if (!network) {
    367     ChangeState(NULL, PLAN_ACTIVATION_ERROR,
    368                 GetErrorMessage(kErrorNoService));
    369     return;
    370   }
    371   if (state_ == PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING ||
    372       state_ == PLAN_ACTIVATION_SHOWING_PAYMENT) {
    373     if (success) {
    374       payment_reconnect_count_ = 0;
    375       ChangeState(network, PLAN_ACTIVATION_SHOWING_PAYMENT, std::string());
    376     } else {
    377       // There is no point in forcing reconnecting the cellular network if the
    378       // activation should not be done over it.
    379       if (network->activation_type() == shill::kActivationTypeNonCellular)
    380         return;
    381 
    382       payment_reconnect_count_++;
    383       if (payment_reconnect_count_ > kMaxPortalReconnectCount) {
    384         ChangeState(NULL, PLAN_ACTIVATION_ERROR,
    385                     GetErrorMessage(kErrorNoService));
    386         return;
    387       }
    388 
    389       // Reconnect and try and load the frame again.
    390       ChangeState(network,
    391                   PLAN_ACTIVATION_RECONNECTING,
    392                   GetErrorMessage(kFailedPaymentError));
    393     }
    394   } else {
    395     NOTREACHED() << "Called paymentPortalLoad while in unexpected state: "
    396                  << GetStateDescription(state_);
    397   }
    398 }
    399 
    400 void MobileActivator::StartOTASPTimer() {
    401   pending_activation_request_ = false;
    402   state_duration_timer_.Start(
    403       FROM_HERE,
    404       base::TimeDelta::FromMilliseconds(kOTASPRetryDelay),
    405       this, &MobileActivator::HandleOTASPTimeout);
    406 }
    407 
    408 void MobileActivator::StartActivation() {
    409   UMA_HISTOGRAM_COUNTS("Cellular.MobileSetupStart", 1);
    410   const NetworkState* network = GetNetworkState(service_path_);
    411   // Check if we can start activation process.
    412   if (!network) {
    413     NetworkStateHandler::TechnologyState technology_state =
    414         NetworkHandler::Get()->network_state_handler()->GetTechnologyState(
    415             NetworkTypePattern::Cellular());
    416     std::string error;
    417     if (technology_state == NetworkStateHandler::TECHNOLOGY_UNAVAILABLE) {
    418       error = kErrorNoDevice;
    419     } else if (technology_state != NetworkStateHandler::TECHNOLOGY_ENABLED) {
    420       error = kErrorDisabled;
    421     } else {
    422       error = kErrorNoService;
    423     }
    424     ChangeState(NULL, PLAN_ACTIVATION_ERROR, GetErrorMessage(error));
    425     return;
    426   }
    427 
    428   // Start monitoring network property changes.
    429   NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
    430 
    431   if (network->activation_type() == shill::kActivationTypeNonCellular)
    432       StartActivationOverNonCellularNetwork();
    433   else if (network->activation_type() == shill::kActivationTypeOTA)
    434       StartActivationOTA();
    435   else if (network->activation_type() == shill::kActivationTypeOTASP)
    436       StartActivationOTASP();
    437 }
    438 
    439 void MobileActivator::StartActivationOverNonCellularNetwork() {
    440   // Fast forward to payment portal loading.
    441   const NetworkState* network = GetNetworkState(service_path_);
    442   if (!network) {
    443     LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    444     return;
    445   }
    446 
    447   ChangeState(
    448       network,
    449       (network->activation_state() == shill::kActivationStateActivated) ?
    450       PLAN_ACTIVATION_DONE :
    451       PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING,
    452       "" /* error_description */);
    453 
    454   RefreshCellularNetworks();
    455 }
    456 
    457 void MobileActivator::StartActivationOTA() {
    458   // Connect to the network if we don't currently have access.
    459   const NetworkState* network = GetNetworkState(service_path_);
    460   if (!network) {
    461     LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    462     return;
    463   }
    464 
    465   const NetworkState* default_network = GetDefaultNetwork();
    466   bool is_online_or_portal = default_network &&
    467       (default_network->connection_state() == shill::kStateOnline ||
    468        default_network->connection_state() == shill::kStatePortal);
    469   if (!is_online_or_portal)
    470     ConnectNetwork(network);
    471 
    472   ChangeState(network, PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING,
    473               "" /* error_description */);
    474   RefreshCellularNetworks();
    475 }
    476 
    477 void MobileActivator::StartActivationOTASP() {
    478   const NetworkState* network = GetNetworkState(service_path_);
    479   if (!network) {
    480     LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    481     return;
    482   }
    483 
    484   if (HasRecentCellularPlanPayment() &&
    485       (network->activation_state() ==
    486        shill::kActivationStatePartiallyActivated)) {
    487     // Try to start with OTASP immediately if we have received payment recently.
    488     state_ = PLAN_ACTIVATION_START_OTASP;
    489   } else {
    490     state_ =  PLAN_ACTIVATION_START;
    491   }
    492 
    493   EvaluateCellularNetwork(network);
    494 }
    495 
    496 void MobileActivator::RetryOTASP() {
    497   DCHECK(state_ == PLAN_ACTIVATION_DELAY_OTASP);
    498   StartOTASP();
    499 }
    500 
    501 void MobileActivator::StartOTASP() {
    502   const NetworkState* network = GetNetworkState(service_path_);
    503   if (!network) {
    504     LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    505     return;
    506   }
    507 
    508   ChangeState(network, PLAN_ACTIVATION_START_OTASP, std::string());
    509   EvaluateCellularNetwork(network);
    510 }
    511 
    512 void MobileActivator::HandleOTASPTimeout() {
    513   LOG(WARNING) << "OTASP seems to be taking too long.";
    514   const NetworkState* network = GetNetworkState(service_path_);
    515   if (!network) {
    516     LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    517     return;
    518   }
    519 
    520   // We're here because one of OTASP steps is taking too long to complete.
    521   // Usually, this means something bad has happened below us.
    522   if (state_ == PLAN_ACTIVATION_INITIATING_ACTIVATION) {
    523     ++initial_OTASP_attempts_;
    524     if (initial_OTASP_attempts_ <= kMaxOTASPTries) {
    525       ChangeState(network,
    526                   PLAN_ACTIVATION_RECONNECTING,
    527                   GetErrorMessage(kErrorDefault));
    528       return;
    529     }
    530   } else if (state_ == PLAN_ACTIVATION_TRYING_OTASP) {
    531     ++trying_OTASP_attempts_;
    532     if (trying_OTASP_attempts_ <= kMaxOTASPTries) {
    533       ChangeState(network,
    534                   PLAN_ACTIVATION_RECONNECTING,
    535                   GetErrorMessage(kErrorDefault));
    536       return;
    537     }
    538   } else if (state_ == PLAN_ACTIVATION_OTASP) {
    539     ++final_OTASP_attempts_;
    540     if (final_OTASP_attempts_ <= kMaxOTASPTries) {
    541       // Give the portal time to propagate all those magic bits.
    542       ChangeState(network,
    543                   PLAN_ACTIVATION_DELAY_OTASP,
    544                   GetErrorMessage(kErrorDefault));
    545       return;
    546     }
    547   } else {
    548     LOG(ERROR) << "OTASP timed out from a non-OTASP wait state?";
    549   }
    550   LOG(ERROR) << "OTASP failed too many times; aborting.";
    551   ChangeState(network,
    552               PLAN_ACTIVATION_ERROR,
    553               GetErrorMessage(kErrorDefault));
    554 }
    555 
    556 void MobileActivator::ConnectNetwork(const NetworkState* network) {
    557   NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
    558       network->path(),
    559       base::Bind(&base::DoNothing),
    560       network_handler::ErrorCallback(),
    561       false /* check_error_state */);
    562 }
    563 
    564 void MobileActivator::ForceReconnect(const NetworkState* network,
    565                                      PlanActivationState next_state) {
    566   DCHECK(network);
    567   // Store away our next destination for when we complete.
    568   post_reconnect_state_ = next_state;
    569   UMA_HISTOGRAM_COUNTS("Cellular.ActivationRetry", 1);
    570   // First, disconnect...
    571   VLOG(1) << "Disconnecting from " << network->path();
    572   // Explicit service Disconnect()s disable autoconnect on the service until
    573   // Connect() is called on the service again.  Hence this dance to explicitly
    574   // call Connect().
    575   NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
    576       network->path(),
    577       base::Bind(&base::DoNothing),
    578       network_handler::ErrorCallback());
    579   // Keep trying to connect until told otherwise.
    580   continue_reconnect_timer_.Stop();
    581   continue_reconnect_timer_.Start(
    582       FROM_HERE,
    583       base::TimeDelta::FromMilliseconds(kReconnectDelayMS),
    584       this, &MobileActivator::ContinueConnecting);
    585   // If we don't ever connect again, we're going to call this a failure.
    586   reconnect_timeout_timer_.Stop();
    587   reconnect_timeout_timer_.Start(
    588       FROM_HERE,
    589       base::TimeDelta::FromMilliseconds(kMaxReconnectTime),
    590       this, &MobileActivator::ReconnectTimedOut);
    591 }
    592 
    593 void MobileActivator::ReconnectTimedOut() {
    594   LOG(ERROR) << "Ending activation attempt after failing to reconnect.";
    595   const NetworkState* network = GetNetworkState(service_path_);
    596   if (!network) {
    597     LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    598     return;
    599   }
    600 
    601   ChangeState(network,
    602               PLAN_ACTIVATION_ERROR,
    603               GetErrorMessage(kFailedConnectivity));
    604 }
    605 
    606 void MobileActivator::ContinueConnecting() {
    607   const NetworkState* network = GetNetworkState(service_path_);
    608   if (network && network->IsConnectedState()) {
    609     if (network->connection_state() == shill::kStatePortal &&
    610         network->error() == shill::kErrorDNSLookupFailed) {
    611       // It isn't an error to be in a restricted pool, but if DNS doesn't work,
    612       // then we're not getting traffic through at all.  Just disconnect and
    613       // try again.
    614       NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
    615           network->path(),
    616           base::Bind(&base::DoNothing),
    617           network_handler::ErrorCallback());
    618       return;
    619     }
    620     // Stop this callback
    621     continue_reconnect_timer_.Stop();
    622     EvaluateCellularNetwork(network);
    623   } else {
    624     LOG(WARNING) << "Connect failed, will try again in a little bit.";
    625     if (network) {
    626       VLOG(1) << "Connecting to: " << network->path();
    627       ash::network_connect::ConnectToNetwork(network->path());
    628     }
    629   }
    630 }
    631 
    632 void MobileActivator::RefreshCellularNetworks() {
    633   if (state_ == PLAN_ACTIVATION_PAGE_LOADING ||
    634       state_ == PLAN_ACTIVATION_DONE ||
    635       state_ == PLAN_ACTIVATION_ERROR) {
    636     return;
    637   }
    638 
    639   const NetworkState* network = GetNetworkState(service_path_);
    640   if (!network) {
    641     LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    642     return;
    643   }
    644 
    645   if (IsSimpleActivationFlow(network)) {
    646     bool waiting = (state_ == PLAN_ACTIVATION_WAITING_FOR_CONNECTION);
    647     // We're only interested in whether or not we have access to the payment
    648     // portal (regardless of which network we use to access it), so check
    649     // the default network connection state. The default network is the network
    650     // used to route default traffic. Also, note that we can access the
    651     // payment portal over a cellular network in the portalled state.
    652     const NetworkState* default_network = GetDefaultNetwork();
    653     bool is_online_or_portal = default_network &&
    654         (default_network->connection_state() == shill::kStateOnline ||
    655          (default_network->type() == shill::kTypeCellular &&
    656           default_network->connection_state() == shill::kStatePortal));
    657     if (waiting && is_online_or_portal) {
    658       ChangeState(network, post_reconnect_state_, "");
    659     } else if (!waiting && !is_online_or_portal) {
    660       ChangeState(network, PLAN_ACTIVATION_WAITING_FOR_CONNECTION, "");
    661     }
    662   }
    663 
    664   EvaluateCellularNetwork(network);
    665 }
    666 
    667 const NetworkState* MobileActivator::GetNetworkState(
    668     const std::string& service_path) {
    669   return NetworkHandler::Get()->network_state_handler()->GetNetworkState(
    670       service_path);
    671 }
    672 
    673 const NetworkState* MobileActivator::GetDefaultNetwork() {
    674   return NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
    675 }
    676 
    677 void MobileActivator::EvaluateCellularNetwork(const NetworkState* network) {
    678   if (terminated_) {
    679     LOG(ERROR) << "Tried to run MobileActivator state machine while "
    680                << "terminated.";
    681     return;
    682   }
    683 
    684   if (!network) {
    685     LOG(WARNING) << "Cellular service lost";
    686     return;
    687   }
    688 
    689   LOG(WARNING) << "Cellular:\n  service state=" << network->connection_state()
    690                << "\n  ui=" << GetStateDescription(state_)
    691                << "\n  activation=" << network->activation_state()
    692                << "\n  error=" << network->error()
    693                << "\n  setvice_path=" << network->path()
    694                << "\n  connected=" << network->IsConnectedState();
    695 
    696   // If the network is activated over non cellular network or OTA, the
    697   // activator state does not depend on the network's own state.
    698   if (IsSimpleActivationFlow(network))
    699     return;
    700 
    701   std::string error_description;
    702   PlanActivationState new_state = PickNextState(network, &error_description);
    703 
    704   ChangeState(network, new_state, error_description);
    705 }
    706 
    707 MobileActivator::PlanActivationState MobileActivator::PickNextState(
    708     const NetworkState* network, std::string* error_description) const {
    709   PlanActivationState new_state = state_;
    710   if (!network->IsConnectedState())
    711     new_state = PickNextOfflineState(network);
    712   else
    713     new_state = PickNextOnlineState(network);
    714   if (new_state != PLAN_ACTIVATION_ERROR &&
    715       GotActivationError(network, error_description)) {
    716     // Check for this special case when we try to do activate partially
    717     // activated device. If that attempt failed, try to disconnect to clear the
    718     // state and reconnect again.
    719     const std::string& activation = network->activation_state();
    720     if ((activation == shill::kActivationStatePartiallyActivated ||
    721          activation == shill::kActivationStateActivating) &&
    722         (network->error().empty() ||
    723          network->error() == shill::kErrorOtaspFailed) &&
    724         network->connection_state() == shill::kStateActivationFailure) {
    725       NET_LOG_EVENT("Activation failure detected ", network->path());
    726       switch (state_) {
    727         case PLAN_ACTIVATION_OTASP:
    728           new_state = PLAN_ACTIVATION_DELAY_OTASP;
    729           break;
    730         case PLAN_ACTIVATION_INITIATING_ACTIVATION:
    731         case PLAN_ACTIVATION_TRYING_OTASP:
    732           new_state = PLAN_ACTIVATION_START;
    733           break;
    734         case PLAN_ACTIVATION_START:
    735           // We are just starting, so this must be previous activation attempt
    736           // failure.
    737           new_state = PLAN_ACTIVATION_TRYING_OTASP;
    738           break;
    739         case PLAN_ACTIVATION_DELAY_OTASP:
    740           new_state = state_;
    741           break;
    742         default:
    743           new_state = PLAN_ACTIVATION_ERROR;
    744           break;
    745       }
    746     } else {
    747       LOG(WARNING) << "Unexpected activation failure for " << network->path();
    748       new_state = PLAN_ACTIVATION_ERROR;
    749     }
    750   }
    751 
    752   if (new_state == PLAN_ACTIVATION_ERROR && !error_description->length())
    753     *error_description = GetErrorMessage(kErrorDefault);
    754   return new_state;
    755 }
    756 
    757 MobileActivator::PlanActivationState MobileActivator::PickNextOfflineState(
    758     const NetworkState* network) const {
    759   PlanActivationState new_state = state_;
    760   const std::string& activation = network->activation_state();
    761   switch (state_) {
    762     case PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING:
    763     case PLAN_ACTIVATION_SHOWING_PAYMENT:
    764       if (!IsSimpleActivationFlow(network))
    765         new_state = PLAN_ACTIVATION_RECONNECTING;
    766       break;
    767     case PLAN_ACTIVATION_START:
    768       if (activation == shill::kActivationStateActivated) {
    769         if (network->connection_state() == shill::kStatePortal)
    770           new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING;
    771         else
    772           new_state = PLAN_ACTIVATION_DONE;
    773       } else if (activation == shill::kActivationStatePartiallyActivated) {
    774         new_state = PLAN_ACTIVATION_TRYING_OTASP;
    775       } else {
    776         new_state = PLAN_ACTIVATION_INITIATING_ACTIVATION;
    777       }
    778       break;
    779     default:
    780       VLOG(1) << "Waiting for cellular service to connect.";
    781       break;
    782   }
    783   return new_state;
    784 }
    785 
    786 MobileActivator::PlanActivationState MobileActivator::PickNextOnlineState(
    787     const NetworkState* network) const {
    788   PlanActivationState new_state = state_;
    789   const std::string& activation = network->activation_state();
    790   switch (state_) {
    791     case PLAN_ACTIVATION_START:
    792       if (activation == shill::kActivationStateActivated) {
    793         if (network->connection_state() == shill::kStateOnline)
    794           new_state = PLAN_ACTIVATION_DONE;
    795         else
    796           new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING;
    797       } else if (activation == shill::kActivationStatePartiallyActivated) {
    798         new_state = PLAN_ACTIVATION_TRYING_OTASP;
    799       } else {
    800         new_state = PLAN_ACTIVATION_INITIATING_ACTIVATION;
    801       }
    802       break;
    803     case PLAN_ACTIVATION_START_OTASP: {
    804       if (activation == shill::kActivationStatePartiallyActivated) {
    805           new_state = PLAN_ACTIVATION_OTASP;
    806       } else if (activation == shill::kActivationStateActivated) {
    807         new_state = PLAN_ACTIVATION_RECONNECTING;
    808       } else {
    809         LOG(WARNING) << "Unexpected activation state for device "
    810                      << network->path();
    811       }
    812       break;
    813     }
    814     case PLAN_ACTIVATION_DELAY_OTASP:
    815       // Just ignore any changes until the OTASP retry timer kicks in.
    816       break;
    817     case PLAN_ACTIVATION_INITIATING_ACTIVATION: {
    818       if (pending_activation_request_) {
    819         VLOG(1) << "Waiting for pending activation attempt to finish";
    820       } else if (activation == shill::kActivationStateActivated ||
    821                  activation == shill::kActivationStatePartiallyActivated) {
    822         new_state = PLAN_ACTIVATION_START;
    823       } else if (activation == shill::kActivationStateNotActivated ||
    824                  activation == shill::kActivationStateActivating) {
    825         // Wait in this state until activation state changes.
    826       } else {
    827         LOG(WARNING) << "Unknown transition";
    828       }
    829       break;
    830     }
    831     case PLAN_ACTIVATION_OTASP:
    832     case PLAN_ACTIVATION_TRYING_OTASP:
    833       if (pending_activation_request_) {
    834         VLOG(1) << "Waiting for pending activation attempt to finish";
    835       } else if (activation == shill::kActivationStateNotActivated ||
    836                  activation == shill::kActivationStateActivating) {
    837         VLOG(1) << "Waiting for the OTASP to finish and the service to "
    838                 << "come back online";
    839       } else if (activation == shill::kActivationStateActivated) {
    840         new_state = PLAN_ACTIVATION_DONE;
    841       } else {
    842         new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING;
    843       }
    844       break;
    845     case PLAN_ACTIVATION_RECONNECTING_PAYMENT:
    846       if (network->connection_state() != shill::kStatePortal &&
    847           activation == shill::kActivationStateActivated)
    848         // We're not portalled, and we're already activated, so we're online!
    849         new_state = PLAN_ACTIVATION_DONE;
    850       else
    851         new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING;
    852       break;
    853     // Initial state
    854     case PLAN_ACTIVATION_PAGE_LOADING:
    855       break;
    856     // Just ignore all signals until the site confirms payment.
    857     case PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING:
    858     case PLAN_ACTIVATION_SHOWING_PAYMENT:
    859     case PLAN_ACTIVATION_WAITING_FOR_CONNECTION:
    860       break;
    861     // Go where we decided earlier.
    862     case PLAN_ACTIVATION_RECONNECTING:
    863       new_state = post_reconnect_state_;
    864       break;
    865     // Activation completed/failed, ignore network changes.
    866     case PLAN_ACTIVATION_DONE:
    867     case PLAN_ACTIVATION_ERROR:
    868       break;
    869   }
    870 
    871   return new_state;
    872 }
    873 
    874 // Debugging helper function, will take it out at the end.
    875 const char* MobileActivator::GetStateDescription(PlanActivationState state) {
    876   switch (state) {
    877     case PLAN_ACTIVATION_PAGE_LOADING:
    878       return "PAGE_LOADING";
    879     case PLAN_ACTIVATION_START:
    880       return "ACTIVATION_START";
    881     case PLAN_ACTIVATION_INITIATING_ACTIVATION:
    882       return "INITIATING_ACTIVATION";
    883     case PLAN_ACTIVATION_TRYING_OTASP:
    884       return "TRYING_OTASP";
    885     case PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING:
    886       return "PAYMENT_PORTAL_LOADING";
    887     case PLAN_ACTIVATION_SHOWING_PAYMENT:
    888       return "SHOWING_PAYMENT";
    889     case PLAN_ACTIVATION_RECONNECTING_PAYMENT:
    890       return "RECONNECTING_PAYMENT";
    891     case PLAN_ACTIVATION_DELAY_OTASP:
    892       return "DELAY_OTASP";
    893     case PLAN_ACTIVATION_START_OTASP:
    894       return "START_OTASP";
    895     case PLAN_ACTIVATION_OTASP:
    896       return "OTASP";
    897     case PLAN_ACTIVATION_DONE:
    898       return "DONE";
    899     case PLAN_ACTIVATION_ERROR:
    900       return "ERROR";
    901     case PLAN_ACTIVATION_RECONNECTING:
    902       return "RECONNECTING";
    903     case PLAN_ACTIVATION_WAITING_FOR_CONNECTION:
    904       return "WAITING FOR CONNECTION";
    905   }
    906   return "UNKNOWN";
    907 }
    908 
    909 
    910 void MobileActivator::CompleteActivation() {
    911   // Remove observers, we are done with this page.
    912   NetworkHandler::Get()->network_state_handler()->
    913       RemoveObserver(this, FROM_HERE);
    914 
    915   // Reactivate other types of connections if we have
    916   // shut them down previously.
    917   ReEnableCertRevocationChecking();
    918 }
    919 
    920 bool MobileActivator::RunningActivation() const {
    921   return !(state_ == PLAN_ACTIVATION_DONE ||
    922            state_ == PLAN_ACTIVATION_ERROR ||
    923            state_ == PLAN_ACTIVATION_PAGE_LOADING);
    924 }
    925 
    926 void MobileActivator::HandleActivationFailure(
    927     const std::string& service_path,
    928     PlanActivationState new_state,
    929     const std::string& error_name,
    930     scoped_ptr<base::DictionaryValue> error_data) {
    931   pending_activation_request_ = false;
    932   const NetworkState* network = GetNetworkState(service_path);
    933   if (!network) {
    934     NET_LOG_ERROR("Cellular service no longer exists", service_path);
    935     return;
    936   }
    937   UMA_HISTOGRAM_COUNTS("Cellular.ActivationFailure", 1);
    938   NET_LOG_ERROR("Failed to call Activate() on service", service_path);
    939   if (new_state == PLAN_ACTIVATION_OTASP) {
    940     ChangeState(network, PLAN_ACTIVATION_DELAY_OTASP, std::string());
    941   } else {
    942     ChangeState(network,
    943                 PLAN_ACTIVATION_ERROR,
    944                 GetErrorMessage(kFailedConnectivity));
    945   }
    946 }
    947 
    948 void MobileActivator::RequestCellularActivation(
    949     const NetworkState* network,
    950     const base::Closure& success_callback,
    951     const network_handler::ErrorCallback& error_callback) {
    952   DCHECK(network);
    953   NET_LOG_EVENT("Activating cellular service", network->path());
    954   UMA_HISTOGRAM_COUNTS("Cellular.ActivationTry", 1);
    955   pending_activation_request_ = true;
    956   NetworkHandler::Get()->network_activation_handler()->
    957       Activate(network->path(),
    958                "",  // carrier
    959                success_callback,
    960                error_callback);
    961 }
    962 
    963 void MobileActivator::ChangeState(const NetworkState* network,
    964                                   PlanActivationState new_state,
    965                                   std::string error_description) {
    966   // Report an error, by transitioning into a PLAN_ACTIVATION_ERROR state with
    967   // a "no service" error instead, if no network state is available (e.g. the
    968   // cellular service no longer exists) when we are transitioning into certain
    969   // plan activation state.
    970   if (!network) {
    971     switch (new_state) {
    972       case PLAN_ACTIVATION_INITIATING_ACTIVATION:
    973       case PLAN_ACTIVATION_TRYING_OTASP:
    974       case PLAN_ACTIVATION_OTASP:
    975       case PLAN_ACTIVATION_DONE:
    976         new_state = PLAN_ACTIVATION_ERROR;
    977         error_description = GetErrorMessage(kErrorNoService);
    978       default:
    979         break;
    980     }
    981   }
    982 
    983   static bool first_time = true;
    984   VLOG(1) << "Activation state flip old = "
    985           << GetStateDescription(state_)
    986           << ", new = " << GetStateDescription(new_state);
    987   if (state_ == new_state && !first_time)
    988     return;
    989   first_time = false;
    990   VLOG(1) << "Transitioning...";
    991 
    992   // Kill all the possible timers and callbacks we might have outstanding.
    993   state_duration_timer_.Stop();
    994   continue_reconnect_timer_.Stop();
    995   reconnect_timeout_timer_.Stop();
    996   const PlanActivationState old_state = state_;
    997   state_ = new_state;
    998 
    999   // Signal to observers layer that the state is changing.
   1000   FOR_EACH_OBSERVER(Observer, observers_,
   1001       OnActivationStateChanged(network, state_, error_description));
   1002 
   1003   // Pick action that should happen on entering the new state.
   1004   switch (new_state) {
   1005     case PLAN_ACTIVATION_START:
   1006       break;
   1007     case PLAN_ACTIVATION_DELAY_OTASP: {
   1008       UMA_HISTOGRAM_COUNTS("Cellular.RetryOTASP", 1);
   1009       BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
   1010           base::Bind(&MobileActivator::RetryOTASP, AsWeakPtr()),
   1011           base::TimeDelta::FromMilliseconds(kOTASPRetryDelay));
   1012       break;
   1013     }
   1014     case PLAN_ACTIVATION_START_OTASP:
   1015       break;
   1016     case PLAN_ACTIVATION_INITIATING_ACTIVATION:
   1017     case PLAN_ACTIVATION_TRYING_OTASP:
   1018     case PLAN_ACTIVATION_OTASP: {
   1019       DCHECK(network);
   1020       network_handler::ErrorCallback on_activation_error =
   1021           base::Bind(&MobileActivator::HandleActivationFailure, AsWeakPtr(),
   1022                      network->path(),
   1023                      new_state);
   1024       RequestCellularActivation(
   1025           network,
   1026           base::Bind(&MobileActivator::StartOTASPTimer, AsWeakPtr()),
   1027           on_activation_error);
   1028       }
   1029       break;
   1030     case PLAN_ACTIVATION_PAGE_LOADING:
   1031       return;
   1032     case PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING:
   1033     case PLAN_ACTIVATION_SHOWING_PAYMENT:
   1034     case PLAN_ACTIVATION_RECONNECTING_PAYMENT:
   1035       // Fix for fix SSL for the walled gardens where cert chain verification
   1036       // might not work.
   1037       break;
   1038     case PLAN_ACTIVATION_WAITING_FOR_CONNECTION:
   1039       post_reconnect_state_ = old_state;
   1040       break;
   1041     case PLAN_ACTIVATION_RECONNECTING: {
   1042       PlanActivationState next_state = old_state;
   1043       // Pick where we want to return to after we reconnect.
   1044       switch (old_state) {
   1045         case PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING:
   1046         case PLAN_ACTIVATION_SHOWING_PAYMENT:
   1047           // We decide here what to do next based on the state of the modem.
   1048           next_state = PLAN_ACTIVATION_RECONNECTING_PAYMENT;
   1049           break;
   1050         case PLAN_ACTIVATION_INITIATING_ACTIVATION:
   1051         case PLAN_ACTIVATION_TRYING_OTASP:
   1052           next_state = PLAN_ACTIVATION_START;
   1053           break;
   1054         case PLAN_ACTIVATION_START_OTASP:
   1055         case PLAN_ACTIVATION_OTASP:
   1056           if (!network || !network->IsConnectedState()) {
   1057             next_state = PLAN_ACTIVATION_START_OTASP;
   1058           } else {
   1059             // We're online, which means we've conspired with
   1060             // PickNextOnlineState to reconnect after activation (that's the
   1061             // only way we see this transition).  Thus, after we reconnect, we
   1062             // should be done.
   1063             next_state = PLAN_ACTIVATION_DONE;
   1064           }
   1065           break;
   1066         default:
   1067           LOG(ERROR) << "Transitioned to RECONNECTING from an unexpected "
   1068                      << "state.";
   1069           break;
   1070       }
   1071       if (network)
   1072         ForceReconnect(network, next_state);
   1073       break;
   1074     }
   1075     case PLAN_ACTIVATION_DONE:
   1076       DCHECK(network);
   1077       CompleteActivation();
   1078       UMA_HISTOGRAM_COUNTS("Cellular.MobileSetupSucceeded", 1);
   1079       break;
   1080     case PLAN_ACTIVATION_ERROR:
   1081       CompleteActivation();
   1082       UMA_HISTOGRAM_COUNTS("Cellular.PlanFailed", 1);
   1083       break;
   1084     default:
   1085       break;
   1086   }
   1087 }
   1088 
   1089 void MobileActivator::ReEnableCertRevocationChecking() {
   1090   // Check that both the browser process and prefs exist before trying to
   1091   // use them, since this method can be called by the destructor while Chrome
   1092   // is shutting down, during which either could be NULL.
   1093   if (!g_browser_process)
   1094     return;
   1095   PrefService* prefs = g_browser_process->local_state();
   1096   if (!prefs)
   1097     return;
   1098   if (reenable_cert_check_) {
   1099     prefs->SetBoolean(prefs::kCertRevocationCheckingEnabled,
   1100                       true);
   1101     reenable_cert_check_ = false;
   1102   }
   1103 }
   1104 
   1105 void MobileActivator::DisableCertRevocationChecking() {
   1106   // Disable SSL cert checks since we might be performing activation in the
   1107   // restricted pool.
   1108   // TODO(rkc): We want to do this only if on Cellular.
   1109   PrefService* prefs = g_browser_process->local_state();
   1110   if (!reenable_cert_check_ &&
   1111       prefs->GetBoolean(
   1112           prefs::kCertRevocationCheckingEnabled)) {
   1113     reenable_cert_check_ = true;
   1114     prefs->SetBoolean(prefs::kCertRevocationCheckingEnabled, false);
   1115   }
   1116 }
   1117 
   1118 bool MobileActivator::GotActivationError(
   1119     const NetworkState* network, std::string* error) const {
   1120   DCHECK(network);
   1121   bool got_error = false;
   1122   const char* error_code = kErrorDefault;
   1123   const std::string& activation = network->activation_state();
   1124 
   1125   // This is the magic for detection of errors in during activation process.
   1126   if (network->connection_state() == shill::kStateFailure &&
   1127       network->error() == shill::kErrorAaaFailed) {
   1128     if (activation == shill::kActivationStatePartiallyActivated) {
   1129       error_code = kErrorBadConnectionPartial;
   1130     } else if (activation == shill::kActivationStateActivated) {
   1131       if (network->roaming() == shill::kRoamingStateHome)
   1132         error_code = kErrorBadConnectionActivated;
   1133       else if (network->roaming() == shill::kRoamingStateRoaming)
   1134         error_code = kErrorRoamingOnConnection;
   1135     }
   1136     got_error = true;
   1137   } else if (network->connection_state() == shill::kStateActivationFailure) {
   1138     if (network->error() == shill::kErrorNeedEvdo) {
   1139       if (activation == shill::kActivationStatePartiallyActivated)
   1140         error_code = kErrorNoEVDO;
   1141     } else if (network->error() == shill::kErrorNeedHomeNetwork) {
   1142       if (activation == shill::kActivationStateNotActivated) {
   1143         error_code = kErrorRoamingActivation;
   1144       } else if (activation == shill::kActivationStatePartiallyActivated) {
   1145         error_code = kErrorRoamingPartiallyActivated;
   1146       }
   1147     }
   1148     got_error = true;
   1149   }
   1150 
   1151   if (got_error)
   1152     *error = GetErrorMessage(error_code);
   1153 
   1154   return got_error;
   1155 }
   1156 
   1157 std::string MobileActivator::GetErrorMessage(const std::string& code) const {
   1158   return cellular_config_->GetErrorMessage(code);
   1159 }
   1160 
   1161 void MobileActivator::SignalCellularPlanPayment() {
   1162   DCHECK(!HasRecentCellularPlanPayment());
   1163   cellular_plan_payment_time_ = base::Time::Now();
   1164 }
   1165 
   1166 bool MobileActivator::HasRecentCellularPlanPayment() const {
   1167   const int kRecentPlanPaymentHours = 6;
   1168   return (base::Time::Now() -
   1169           cellular_plan_payment_time_).InHours() < kRecentPlanPaymentHours;
   1170 }
   1171 
   1172 }  // namespace chromeos
   1173