// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/mobile/mobile_activator.h"

#include <algorithm>
#include <map>
#include <string>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
#include "base/metrics/histogram_macros.h"
#include "base/observer_list_threadsafe.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/pref_names.h"
#include "chromeos/network/device_state.h"
#include "chromeos/network/network_activation_handler.h"
#include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_connect.h"
#include "chromeos/network/network_connection_handler.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_handler_callbacks.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

using content::BrowserThread;

namespace {

// Cellular configuration file path.
const char kCellularConfigPath[] =
    "/usr/share/chromeos-assets/mobile/mobile_config.json";

// Cellular config file field names.
const char kVersionField[] = "version";
const char kErrorsField[] = "errors";

// Number of times we'll try an OTASP before failing the activation process.
const int kMaxOTASPTries = 3;
// Number of times we will retry to reconnect and reload payment portal page.
const int kMaxPortalReconnectCount = 2;
// Time between connection attempts when forcing a reconnect.
const int kReconnectDelayMS = 3000;
// Retry delay after failed OTASP attempt.
const int kOTASPRetryDelay = 40000;
// Maximum amount of time we'll wait for a service to reconnect.
const int kMaxReconnectTime = 30000;

// Error codes matching codes defined in the cellular config file.
const char kErrorDefault[] = "default";
const char kErrorBadConnectionPartial[] = "bad_connection_partial";
const char kErrorBadConnectionActivated[] = "bad_connection_activated";
const char kErrorRoamingOnConnection[] = "roaming_connection";
const char kErrorNoEVDO[] = "no_evdo";
const char kErrorRoamingActivation[] = "roaming_activation";
const char kErrorRoamingPartiallyActivated[] = "roaming_partially_activated";
const char kErrorNoService[] = "no_service";
const char kErrorDisabled[] = "disabled";
const char kErrorNoDevice[] = "no_device";
const char kFailedPaymentError[] = "failed_payment";
const char kFailedConnectivity[] = "connectivity";

// Returns true if the device follows the simple activation flow.
bool IsSimpleActivationFlow(const chromeos::NetworkState* network) {
  return (network->activation_type() == shill::kActivationTypeNonCellular ||
          network->activation_type() == shill::kActivationTypeOTA);
}

}  // namespace

namespace chromeos {

////////////////////////////////////////////////////////////////////////////////
//
// CellularConfigDocument
//
////////////////////////////////////////////////////////////////////////////////
CellularConfigDocument::CellularConfigDocument() {}

std::string CellularConfigDocument::GetErrorMessage(const std::string& code) {
  base::AutoLock create(config_lock_);
  ErrorMap::iterator iter = error_map_.find(code);
  if (iter == error_map_.end())
    return code;
  return iter->second;
}

void CellularConfigDocument::LoadCellularConfigFile() {
  base::AssertBlockingAllowed();

  // Load partner customization startup manifest if it is available.
  base::FilePath config_path(kCellularConfigPath);
  if (!base::PathExists(config_path))
    return;

  if (LoadFromFile(config_path))
    DVLOG(1) << "Cellular config file loaded: " << kCellularConfigPath;
  else
    LOG(ERROR) << "Error loading cellular config file: " << kCellularConfigPath;
}

CellularConfigDocument::~CellularConfigDocument() {}

void CellularConfigDocument::SetErrorMap(
    const ErrorMap& map) {
  base::AutoLock create(config_lock_);
  error_map_.clear();
  error_map_.insert(map.begin(), map.end());
}

bool CellularConfigDocument::LoadFromFile(const base::FilePath& config_path) {
  std::string config;
  if (!base::ReadFileToString(config_path, &config))
    return false;

  std::unique_ptr<base::Value> root =
      base::JSONReader::Read(config, base::JSON_ALLOW_TRAILING_COMMAS);
  DCHECK(root.get() != NULL);
  if (!root.get() || !root->is_dict()) {
    LOG(WARNING) << "Bad cellular config file";
    return false;
  }

  base::DictionaryValue* root_dict =
      static_cast<base::DictionaryValue*>(root.get());
  if (!root_dict->GetString(kVersionField, &version_)) {
    LOG(WARNING) << "Cellular config file missing version";
    return false;
  }
  ErrorMap error_map;
  base::DictionaryValue* errors = NULL;
  if (!root_dict->GetDictionary(kErrorsField, &errors))
    return false;
  for (base::DictionaryValue::Iterator it(*errors);
      !it.IsAtEnd(); it.Advance()) {
    std::string value;
    if (!it.value().GetAsString(&value)) {
      LOG(WARNING) << "Bad cellular config error value";
      return false;
    }
    error_map.insert(ErrorMap::value_type(it.key(), value));
  }
  SetErrorMap(error_map);
  return true;
}

////////////////////////////////////////////////////////////////////////////////
//
// MobileActivator
//
////////////////////////////////////////////////////////////////////////////////
MobileActivator::MobileActivator()
    : cellular_config_(new CellularConfigDocument()),
      state_(PLAN_ACTIVATION_PAGE_LOADING),
      reenable_cert_check_(false),
      terminated_(true),
      pending_activation_request_(false),
      connection_retry_count_(0),
      initial_OTASP_attempts_(0),
      trying_OTASP_attempts_(0),
      final_OTASP_attempts_(0),
      payment_reconnect_count_(0),
      weak_ptr_factory_(this) {
}

MobileActivator::~MobileActivator() {
  TerminateActivation();
}

MobileActivator* MobileActivator::GetInstance() {
  return base::Singleton<MobileActivator>::get();
}

void MobileActivator::TerminateActivation() {
  state_duration_timer_.Stop();
  continue_reconnect_timer_.Stop();
  reconnect_timeout_timer_.Stop();

  if (NetworkHandler::IsInitialized()) {
    NetworkHandler::Get()->network_state_handler()->
        RemoveObserver(this, FROM_HERE);
  }
  ReEnableCertRevocationChecking();
  meid_.clear();
  iccid_.clear();
  service_path_.clear();
  device_path_.clear();
  state_ = PLAN_ACTIVATION_PAGE_LOADING;
  reenable_cert_check_ = false;
  terminated_ = true;
  // Release the previous cellular config and setup a new empty one.
  cellular_config_ = new CellularConfigDocument();
}

void MobileActivator::DefaultNetworkChanged(const NetworkState* network) {
  RefreshCellularNetworks();
}

void MobileActivator::NetworkPropertiesUpdated(const NetworkState* network) {
  if (state_ == PLAN_ACTIVATION_PAGE_LOADING)
    return;

  if (!network || network->type() != shill::kTypeCellular)
    return;

  const DeviceState* device = NetworkHandler::Get()->network_state_handler()->
      GetDeviceState(network->device_path());
  if (!device) {
    LOG(ERROR) << "Cellular device can't be found: " << network->device_path();
    return;
  }
  if (network->device_path() != device_path_) {
    LOG(WARNING) << "Ignoring property update for cellular service "
                 << network->path()
                 << " on unknown device " << network->device_path()
                 << " (Stored device path = " << device_path_ << ")";
    return;
  }

  // A modem reset leads to a new service path. Since we have verified that we
  // are a cellular service on a still valid stored device path, update it.
  service_path_ = network->path();

  EvaluateCellularNetwork(network);
}

void MobileActivator::AddObserver(MobileActivator::Observer* observer) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  observers_.AddObserver(observer);
}

void MobileActivator::RemoveObserver(MobileActivator::Observer* observer) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  observers_.RemoveObserver(observer);
}

void MobileActivator::InitiateActivation(const std::string& service_path) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  const NetworkState* network =  GetNetworkState(service_path);
  if (!network) {
    LOG(WARNING) << "Cellular service can't be found: " << service_path;
    return;
  }
  const DeviceState* device = NetworkHandler::Get()->network_state_handler()->
      GetDeviceState(network->device_path());
  if (!device) {
    LOG(ERROR) << "Cellular device can't be found: " << network->device_path();
    return;
  }

  terminated_ = false;
  meid_ = device->meid();
  iccid_ = device->iccid();
  service_path_ = service_path;
  device_path_ = network->device_path();

  ChangeState(network, PLAN_ACTIVATION_PAGE_LOADING, "");

  base::PostTaskWithTraitsAndReply(
      FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
      base::BindOnce(&CellularConfigDocument::LoadCellularConfigFile,
                     cellular_config_.get()),
      base::BindOnce(&MobileActivator::ContinueActivation, AsWeakPtr()));
}

void MobileActivator::ContinueActivation() {
  NetworkHandler::Get()->network_configuration_handler()->GetShillProperties(
      service_path_,
      base::Bind(&MobileActivator::GetPropertiesAndContinueActivation,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&MobileActivator::GetPropertiesFailure,
                 weak_ptr_factory_.GetWeakPtr()));
}

void MobileActivator::GetPropertiesAndContinueActivation(
    const std::string& service_path,
    const base::DictionaryValue& properties) {
  if (service_path != service_path_) {
    NET_LOG_EVENT("MobileActivator::GetProperties received for stale network",
                  service_path);
    return;  // Edge case; abort.
  }
  const base::DictionaryValue* payment_dict;
  std::string usage_url, payment_url;
  if (!properties.GetStringWithoutPathExpansion(
          shill::kUsageURLProperty, &usage_url) ||
      !properties.GetDictionaryWithoutPathExpansion(
          shill::kPaymentPortalProperty, &payment_dict) ||
      !payment_dict->GetStringWithoutPathExpansion(
          shill::kPaymentPortalURL, &payment_url)) {
    NET_LOG_ERROR("MobileActivator missing properties", service_path_);
    return;
  }

  if (payment_url.empty() && usage_url.empty())
    return;

  DisableCertRevocationChecking();

  // We want shill to connect us after activations, so enable autoconnect.
  base::DictionaryValue auto_connect_property;
  auto_connect_property.SetBoolean(shill::kAutoConnectProperty, true);
  NetworkHandler::Get()->network_configuration_handler()->SetShillProperties(
      service_path_, auto_connect_property, base::DoNothing(),
      network_handler::ErrorCallback());
  StartActivation();
}

void MobileActivator::GetPropertiesFailure(
    const std::string& error_name,
    std::unique_ptr<base::DictionaryValue> error_data) {
  NET_LOG_ERROR("MobileActivator GetProperties Failed: " + error_name,
                service_path_);
}

void MobileActivator::OnSetTransactionStatus(bool success) {
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
      base::Bind(&MobileActivator::HandleSetTransactionStatus,
                 AsWeakPtr(), success));
}

void MobileActivator::HandleSetTransactionStatus(bool success) {
  // The payment is received, try to reconnect and check the status all over
  // again.
  if (success && state_ == PLAN_ACTIVATION_SHOWING_PAYMENT) {
    SignalCellularPlanPayment();
    UMA_HISTOGRAM_COUNTS("Cellular.PaymentReceived", 1);
    const NetworkState* network = GetNetworkState(service_path_);
    if (network && IsSimpleActivationFlow(network)) {
      state_ = PLAN_ACTIVATION_DONE;
      NetworkHandler::Get()->network_activation_handler()->CompleteActivation(
          network->path(), base::DoNothing(), network_handler::ErrorCallback());
    } else {
      StartOTASP();
    }
  } else {
    UMA_HISTOGRAM_COUNTS("Cellular.PaymentFailed", 1);
  }
}

void MobileActivator::OnPortalLoaded(bool success) {
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
      base::Bind(&MobileActivator::HandlePortalLoaded,
                 AsWeakPtr(), success));
}

void MobileActivator::HandlePortalLoaded(bool success) {
  const NetworkState* network = GetNetworkState(service_path_);
  if (!network) {
    ChangeState(NULL, PLAN_ACTIVATION_ERROR,
                GetErrorMessage(kErrorNoService));
    return;
  }
  if (state_ == PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING ||
      state_ == PLAN_ACTIVATION_SHOWING_PAYMENT) {
    if (success) {
      payment_reconnect_count_ = 0;
      ChangeState(network, PLAN_ACTIVATION_SHOWING_PAYMENT, std::string());
    } else {
      // There is no point in forcing reconnecting the cellular network if the
      // activation should not be done over it.
      if (network->activation_type() == shill::kActivationTypeNonCellular)
        return;

      payment_reconnect_count_++;
      if (payment_reconnect_count_ > kMaxPortalReconnectCount) {
        ChangeState(NULL, PLAN_ACTIVATION_ERROR,
                    GetErrorMessage(kErrorNoService));
        return;
      }

      // Reconnect and try and load the frame again.
      ChangeState(network,
                  PLAN_ACTIVATION_RECONNECTING,
                  GetErrorMessage(kFailedPaymentError));
    }
  } else {
    NOTREACHED() << "Called paymentPortalLoad while in unexpected state: "
                 << GetStateDescription(state_);
  }
}

void MobileActivator::StartOTASPTimer() {
  pending_activation_request_ = false;
  state_duration_timer_.Start(
      FROM_HERE,
      base::TimeDelta::FromMilliseconds(kOTASPRetryDelay),
      this, &MobileActivator::HandleOTASPTimeout);
}

void MobileActivator::StartActivation() {
  UMA_HISTOGRAM_COUNTS("Cellular.MobileSetupStart", 1);
  const NetworkState* network = GetNetworkState(service_path_);
  // Check if we can start activation process.
  if (!network) {
    NetworkStateHandler::TechnologyState technology_state =
        NetworkHandler::Get()->network_state_handler()->GetTechnologyState(
            NetworkTypePattern::Cellular());
    std::string error;
    if (technology_state == NetworkStateHandler::TECHNOLOGY_UNAVAILABLE) {
      error = kErrorNoDevice;
    } else if (technology_state != NetworkStateHandler::TECHNOLOGY_ENABLED) {
      error = kErrorDisabled;
    } else {
      error = kErrorNoService;
    }
    ChangeState(NULL, PLAN_ACTIVATION_ERROR, GetErrorMessage(error));
    return;
  }

  // Start monitoring network property changes.
  NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);

  if (network->activation_type() == shill::kActivationTypeNonCellular)
      StartActivationOverNonCellularNetwork();
  else if (network->activation_type() == shill::kActivationTypeOTA)
      StartActivationOTA();
  else if (network->activation_type() == shill::kActivationTypeOTASP)
      StartActivationOTASP();
}

void MobileActivator::StartActivationOverNonCellularNetwork() {
  // Fast forward to payment portal loading.
  const NetworkState* network = GetNetworkState(service_path_);
  if (!network) {
    LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    return;
  }

  ChangeState(
      network,
      (network->activation_state() == shill::kActivationStateActivated) ?
      PLAN_ACTIVATION_DONE :
      PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING,
      "" /* error_description */);

  RefreshCellularNetworks();
}

void MobileActivator::StartActivationOTA() {
  // Connect to the network if we don't currently have access.
  const NetworkState* network = GetNetworkState(service_path_);
  if (!network) {
    LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    return;
  }

  const NetworkState* default_network = GetDefaultNetwork();
  bool is_online_or_portal = default_network &&
      (default_network->connection_state() == shill::kStateOnline ||
       default_network->connection_state() == shill::kStatePortal);
  if (!is_online_or_portal)
    ConnectNetwork(network);

  ChangeState(network, PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING,
              "" /* error_description */);
  RefreshCellularNetworks();
}

void MobileActivator::StartActivationOTASP() {
  const NetworkState* network = GetNetworkState(service_path_);
  if (!network) {
    LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    return;
  }

  if (HasRecentCellularPlanPayment() &&
      (network->activation_state() ==
       shill::kActivationStatePartiallyActivated)) {
    // Try to start with OTASP immediately if we have received payment recently.
    state_ = PLAN_ACTIVATION_START_OTASP;
  } else {
    state_ =  PLAN_ACTIVATION_START;
  }

  EvaluateCellularNetwork(network);
}

void MobileActivator::RetryOTASP() {
  DCHECK(state_ == PLAN_ACTIVATION_DELAY_OTASP);
  StartOTASP();
}

void MobileActivator::StartOTASP() {
  const NetworkState* network = GetNetworkState(service_path_);
  if (!network) {
    LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    return;
  }

  ChangeState(network, PLAN_ACTIVATION_START_OTASP, std::string());
  EvaluateCellularNetwork(network);
}

void MobileActivator::HandleOTASPTimeout() {
  LOG(WARNING) << "OTASP seems to be taking too long.";
  const NetworkState* network = GetNetworkState(service_path_);
  if (!network) {
    LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    return;
  }

  // We're here because one of OTASP steps is taking too long to complete.
  // Usually, this means something bad has happened below us.
  if (state_ == PLAN_ACTIVATION_INITIATING_ACTIVATION) {
    ++initial_OTASP_attempts_;
    if (initial_OTASP_attempts_ <= kMaxOTASPTries) {
      ChangeState(network,
                  PLAN_ACTIVATION_RECONNECTING,
                  GetErrorMessage(kErrorDefault));
      return;
    }
  } else if (state_ == PLAN_ACTIVATION_TRYING_OTASP) {
    ++trying_OTASP_attempts_;
    if (trying_OTASP_attempts_ <= kMaxOTASPTries) {
      ChangeState(network,
                  PLAN_ACTIVATION_RECONNECTING,
                  GetErrorMessage(kErrorDefault));
      return;
    }
  } else if (state_ == PLAN_ACTIVATION_OTASP) {
    ++final_OTASP_attempts_;
    if (final_OTASP_attempts_ <= kMaxOTASPTries) {
      // Give the portal time to propagate all those magic bits.
      ChangeState(network,
                  PLAN_ACTIVATION_DELAY_OTASP,
                  GetErrorMessage(kErrorDefault));
      return;
    }
  } else {
    LOG(ERROR) << "OTASP timed out from a non-OTASP wait state?";
  }
  LOG(ERROR) << "OTASP failed too many times; aborting.";
  ChangeState(network,
              PLAN_ACTIVATION_ERROR,
              GetErrorMessage(kErrorDefault));
}

void MobileActivator::ConnectNetwork(const NetworkState* network) {
  NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
      network->path(), base::DoNothing(), network_handler::ErrorCallback(),
      false /* check_error_state */, ConnectCallbackMode::ON_STARTED);
}

void MobileActivator::ForceReconnect(const NetworkState* network,
                                     PlanActivationState next_state) {
  DCHECK(network);
  // Store away our next destination for when we complete.
  post_reconnect_state_ = next_state;
  UMA_HISTOGRAM_COUNTS("Cellular.ActivationRetry", 1);
  // First, disconnect...
  VLOG(1) << "Disconnecting from " << network->path();
  // Explicit service Disconnect()s disable autoconnect on the service until
  // Connect() is called on the service again.  Hence this dance to explicitly
  // call Connect().
  NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
      network->path(), base::DoNothing(), network_handler::ErrorCallback());
  // Keep trying to connect until told otherwise.
  continue_reconnect_timer_.Stop();
  continue_reconnect_timer_.Start(
      FROM_HERE,
      base::TimeDelta::FromMilliseconds(kReconnectDelayMS),
      this, &MobileActivator::ContinueConnecting);
  // If we don't ever connect again, we're going to call this a failure.
  reconnect_timeout_timer_.Stop();
  reconnect_timeout_timer_.Start(
      FROM_HERE,
      base::TimeDelta::FromMilliseconds(kMaxReconnectTime),
      this, &MobileActivator::ReconnectTimedOut);
}

void MobileActivator::ReconnectTimedOut() {
  LOG(ERROR) << "Ending activation attempt after failing to reconnect.";
  const NetworkState* network = GetNetworkState(service_path_);
  if (!network) {
    LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    return;
  }

  ChangeState(network,
              PLAN_ACTIVATION_ERROR,
              GetErrorMessage(kFailedConnectivity));
}

void MobileActivator::ContinueConnecting() {
  const NetworkState* network = GetNetworkState(service_path_);
  if (network && network->IsConnectedState()) {
    if (network->connection_state() == shill::kStatePortal &&
        network->error() == shill::kErrorDNSLookupFailed) {
      // It isn't an error to be in a restricted pool, but if DNS doesn't work,
      // then we're not getting traffic through at all.  Just disconnect and
      // try again.
      NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
          network->path(), base::DoNothing(), network_handler::ErrorCallback());
      return;
    }
    // Stop this callback
    continue_reconnect_timer_.Stop();
    EvaluateCellularNetwork(network);
  } else {
    LOG(WARNING) << "Connect failed, will try again in a little bit.";
    if (network) {
      VLOG(1) << "Connecting to: " << network->path();
      NetworkConnect::Get()->ConnectToNetworkId(network->guid());
    }
  }
}

void MobileActivator::RefreshCellularNetworks() {
  if (state_ == PLAN_ACTIVATION_PAGE_LOADING ||
      state_ == PLAN_ACTIVATION_DONE ||
      state_ == PLAN_ACTIVATION_ERROR) {
    return;
  }

  const NetworkState* network = GetNetworkState(service_path_);
  if (!network) {
    LOG(WARNING) << "Cellular service can't be found: " << service_path_;
    return;
  }

  if (IsSimpleActivationFlow(network)) {
    bool waiting = (state_ == PLAN_ACTIVATION_WAITING_FOR_CONNECTION);
    // We're only interested in whether or not we have access to the payment
    // portal (regardless of which network we use to access it), so check
    // the default network connection state. The default network is the network
    // used to route default traffic. Also, note that we can access the
    // payment portal over a cellular network in the portalled state.
    const NetworkState* default_network = GetDefaultNetwork();
    bool is_online_or_portal = default_network &&
        (default_network->connection_state() == shill::kStateOnline ||
         (default_network->type() == shill::kTypeCellular &&
          default_network->connection_state() == shill::kStatePortal));
    if (waiting && is_online_or_portal) {
      ChangeState(network, post_reconnect_state_, "");
    } else if (!waiting && !is_online_or_portal) {
      ChangeState(network, PLAN_ACTIVATION_WAITING_FOR_CONNECTION, "");
    }
  }

  EvaluateCellularNetwork(network);
}

const NetworkState* MobileActivator::GetNetworkState(
    const std::string& service_path) {
  return NetworkHandler::Get()->network_state_handler()->GetNetworkState(
      service_path);
}

const NetworkState* MobileActivator::GetDefaultNetwork() {
  return NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
}

void MobileActivator::EvaluateCellularNetwork(const NetworkState* network) {
  if (terminated_) {
    LOG(ERROR) << "Tried to run MobileActivator state machine while "
               << "terminated.";
    return;
  }

  if (!network) {
    LOG(WARNING) << "Cellular service lost";
    return;
  }

  LOG(WARNING) << "Cellular:\n  service state=" << network->connection_state()
               << "\n  ui=" << GetStateDescription(state_)
               << "\n  activation=" << network->activation_state()
               << "\n  error=" << network->error()
               << "\n  setvice_path=" << network->path()
               << "\n  connected=" << network->IsConnectedState();

  // If the network is activated over non cellular network or OTA, the
  // activator state does not depend on the network's own state.
  if (IsSimpleActivationFlow(network))
    return;

  std::string error_description;
  PlanActivationState new_state = PickNextState(network, &error_description);

  ChangeState(network, new_state, error_description);
}

MobileActivator::PlanActivationState MobileActivator::PickNextState(
    const NetworkState* network, std::string* error_description) const {
  PlanActivationState new_state = state_;
  if (!network->IsConnectedState())
    new_state = PickNextOfflineState(network);
  else
    new_state = PickNextOnlineState(network);
  if (new_state != PLAN_ACTIVATION_ERROR &&
      GotActivationError(network, error_description)) {
    // Check for this special case when we try to do activate partially
    // activated device. If that attempt failed, try to disconnect to clear the
    // state and reconnect again.
    const std::string& activation = network->activation_state();
    if ((activation == shill::kActivationStatePartiallyActivated ||
         activation == shill::kActivationStateActivating) &&
        (network->error().empty() ||
         network->error() == shill::kErrorOtaspFailed) &&
        network->connection_state() == shill::kStateActivationFailure) {
      NET_LOG_EVENT("Activation failure detected ", network->path());
      switch (state_) {
        case PLAN_ACTIVATION_OTASP:
          new_state = PLAN_ACTIVATION_DELAY_OTASP;
          break;
        case PLAN_ACTIVATION_INITIATING_ACTIVATION:
        case PLAN_ACTIVATION_TRYING_OTASP:
          new_state = PLAN_ACTIVATION_START;
          break;
        case PLAN_ACTIVATION_START:
          // We are just starting, so this must be previous activation attempt
          // failure.
          new_state = PLAN_ACTIVATION_TRYING_OTASP;
          break;
        case PLAN_ACTIVATION_DELAY_OTASP:
          new_state = state_;
          break;
        default:
          new_state = PLAN_ACTIVATION_ERROR;
          break;
      }
    } else {
      LOG(WARNING) << "Unexpected activation failure for " << network->path();
      new_state = PLAN_ACTIVATION_ERROR;
    }
  }

  if (new_state == PLAN_ACTIVATION_ERROR && !error_description->length())
    *error_description = GetErrorMessage(kErrorDefault);
  return new_state;
}

MobileActivator::PlanActivationState MobileActivator::PickNextOfflineState(
    const NetworkState* network) const {
  PlanActivationState new_state = state_;
  const std::string& activation = network->activation_state();
  switch (state_) {
    case PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING:
    case PLAN_ACTIVATION_SHOWING_PAYMENT:
      if (!IsSimpleActivationFlow(network))
        new_state = PLAN_ACTIVATION_RECONNECTING;
      break;
    case PLAN_ACTIVATION_START:
      if (activation == shill::kActivationStateActivated) {
        if (network->connection_state() == shill::kStatePortal)
          new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING;
        else
          new_state = PLAN_ACTIVATION_DONE;
      } else if (activation == shill::kActivationStatePartiallyActivated) {
        new_state = PLAN_ACTIVATION_TRYING_OTASP;
      } else {
        new_state = PLAN_ACTIVATION_INITIATING_ACTIVATION;
      }
      break;
    default:
      VLOG(1) << "Waiting for cellular service to connect.";
      break;
  }
  return new_state;
}

MobileActivator::PlanActivationState MobileActivator::PickNextOnlineState(
    const NetworkState* network) const {
  PlanActivationState new_state = state_;
  const std::string& activation = network->activation_state();
  switch (state_) {
    case PLAN_ACTIVATION_START:
      if (activation == shill::kActivationStateActivated) {
        if (network->connection_state() == shill::kStateOnline)
          new_state = PLAN_ACTIVATION_DONE;
        else
          new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING;
      } else if (activation == shill::kActivationStatePartiallyActivated) {
        new_state = PLAN_ACTIVATION_TRYING_OTASP;
      } else {
        new_state = PLAN_ACTIVATION_INITIATING_ACTIVATION;
      }
      break;
    case PLAN_ACTIVATION_START_OTASP: {
      if (activation == shill::kActivationStatePartiallyActivated) {
          new_state = PLAN_ACTIVATION_OTASP;
      } else if (activation == shill::kActivationStateActivated) {
        new_state = PLAN_ACTIVATION_RECONNECTING;
      } else {
        LOG(WARNING) << "Unexpected activation state for device "
                     << network->path();
      }
      break;
    }
    case PLAN_ACTIVATION_DELAY_OTASP:
      // Just ignore any changes until the OTASP retry timer kicks in.
      break;
    case PLAN_ACTIVATION_INITIATING_ACTIVATION: {
      if (pending_activation_request_) {
        VLOG(1) << "Waiting for pending activation attempt to finish";
      } else if (activation == shill::kActivationStateActivated ||
                 activation == shill::kActivationStatePartiallyActivated) {
        new_state = PLAN_ACTIVATION_START;
      } else if (activation == shill::kActivationStateNotActivated ||
                 activation == shill::kActivationStateActivating) {
        // Wait in this state until activation state changes.
      } else {
        LOG(WARNING) << "Unknown transition";
      }
      break;
    }
    case PLAN_ACTIVATION_OTASP:
    case PLAN_ACTIVATION_TRYING_OTASP:
      if (pending_activation_request_) {
        VLOG(1) << "Waiting for pending activation attempt to finish";
      } else if (activation == shill::kActivationStateNotActivated ||
                 activation == shill::kActivationStateActivating) {
        VLOG(1) << "Waiting for the OTASP to finish and the service to "
                << "come back online";
      } else if (activation == shill::kActivationStateActivated) {
        new_state = PLAN_ACTIVATION_DONE;
      } else {
        new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING;
      }
      break;
    case PLAN_ACTIVATION_RECONNECTING_PAYMENT:
      if (network->connection_state() != shill::kStatePortal &&
          activation == shill::kActivationStateActivated)
        // We're not portalled, and we're already activated, so we're online!
        new_state = PLAN_ACTIVATION_DONE;
      else
        new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING;
      break;
    // Initial state
    case PLAN_ACTIVATION_PAGE_LOADING:
      break;
    // Just ignore all signals until the site confirms payment.
    case PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING:
    case PLAN_ACTIVATION_SHOWING_PAYMENT:
    case PLAN_ACTIVATION_WAITING_FOR_CONNECTION:
      break;
    // Go where we decided earlier.
    case PLAN_ACTIVATION_RECONNECTING:
      new_state = post_reconnect_state_;
      break;
    // Activation completed/failed, ignore network changes.
    case PLAN_ACTIVATION_DONE:
    case PLAN_ACTIVATION_ERROR:
      break;
  }

  return new_state;
}

// Debugging helper function, will take it out at the end.
const char* MobileActivator::GetStateDescription(PlanActivationState state) {
  switch (state) {
    case PLAN_ACTIVATION_PAGE_LOADING:
      return "PAGE_LOADING";
    case PLAN_ACTIVATION_START:
      return "ACTIVATION_START";
    case PLAN_ACTIVATION_INITIATING_ACTIVATION:
      return "INITIATING_ACTIVATION";
    case PLAN_ACTIVATION_TRYING_OTASP:
      return "TRYING_OTASP";
    case PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING:
      return "PAYMENT_PORTAL_LOADING";
    case PLAN_ACTIVATION_SHOWING_PAYMENT:
      return "SHOWING_PAYMENT";
    case PLAN_ACTIVATION_RECONNECTING_PAYMENT:
      return "RECONNECTING_PAYMENT";
    case PLAN_ACTIVATION_DELAY_OTASP:
      return "DELAY_OTASP";
    case PLAN_ACTIVATION_START_OTASP:
      return "START_OTASP";
    case PLAN_ACTIVATION_OTASP:
      return "OTASP";
    case PLAN_ACTIVATION_DONE:
      return "DONE";
    case PLAN_ACTIVATION_ERROR:
      return "ERROR";
    case PLAN_ACTIVATION_RECONNECTING:
      return "RECONNECTING";
    case PLAN_ACTIVATION_WAITING_FOR_CONNECTION:
      return "WAITING FOR CONNECTION";
  }
  return "UNKNOWN";
}


void MobileActivator::CompleteActivation() {
  // Remove observers, we are done with this page.
  NetworkHandler::Get()->network_state_handler()->
      RemoveObserver(this, FROM_HERE);

  // Reactivate other types of connections if we have
  // shut them down previously.
  ReEnableCertRevocationChecking();
}

bool MobileActivator::RunningActivation() const {
  return !(state_ == PLAN_ACTIVATION_DONE ||
           state_ == PLAN_ACTIVATION_ERROR ||
           state_ == PLAN_ACTIVATION_PAGE_LOADING);
}

void MobileActivator::HandleActivationFailure(
    const std::string& service_path,
    PlanActivationState new_state,
    const std::string& error_name,
    std::unique_ptr<base::DictionaryValue> error_data) {
  pending_activation_request_ = false;
  const NetworkState* network = GetNetworkState(service_path);
  if (!network) {
    NET_LOG_ERROR("Cellular service no longer exists", service_path);
    return;
  }
  UMA_HISTOGRAM_COUNTS("Cellular.ActivationFailure", 1);
  NET_LOG_ERROR("Failed to call Activate() on service", service_path);
  if (new_state == PLAN_ACTIVATION_OTASP) {
    ChangeState(network, PLAN_ACTIVATION_DELAY_OTASP, std::string());
  } else {
    ChangeState(network,
                PLAN_ACTIVATION_ERROR,
                GetErrorMessage(kFailedConnectivity));
  }
}

void MobileActivator::RequestCellularActivation(
    const NetworkState* network,
    const base::Closure& success_callback,
    const network_handler::ErrorCallback& error_callback) {
  DCHECK(network);
  NET_LOG_EVENT("Activating cellular service", network->path());
  UMA_HISTOGRAM_COUNTS("Cellular.ActivationTry", 1);
  pending_activation_request_ = true;
  NetworkHandler::Get()->network_activation_handler()->
      Activate(network->path(),
               "",  // carrier
               success_callback,
               error_callback);
}

void MobileActivator::ChangeState(const NetworkState* network,
                                  PlanActivationState new_state,
                                  std::string error_description) {
  // Report an error, by transitioning into a PLAN_ACTIVATION_ERROR state with
  // a "no service" error instead, if no network state is available (e.g. the
  // cellular service no longer exists) when we are transitioning into certain
  // plan activation state.
  if (!network) {
    switch (new_state) {
      case PLAN_ACTIVATION_INITIATING_ACTIVATION:
      case PLAN_ACTIVATION_TRYING_OTASP:
      case PLAN_ACTIVATION_OTASP:
      case PLAN_ACTIVATION_DONE:
        new_state = PLAN_ACTIVATION_ERROR;
        error_description = GetErrorMessage(kErrorNoService);
        break;
      default:
        break;
    }
  }

  static bool first_time = true;
  VLOG(1) << "Activation state flip old = "
          << GetStateDescription(state_)
          << ", new = " << GetStateDescription(new_state);
  if (state_ == new_state && !first_time)
    return;
  first_time = false;
  VLOG(1) << "Transitioning...";

  // Kill all the possible timers and callbacks we might have outstanding.
  state_duration_timer_.Stop();
  continue_reconnect_timer_.Stop();
  reconnect_timeout_timer_.Stop();
  const PlanActivationState old_state = state_;
  state_ = new_state;

  // Signal to observers layer that the state is changing.
  for (auto& observer : observers_)
    observer.OnActivationStateChanged(network, state_, error_description);

  // Pick action that should happen on entering the new state.
  switch (new_state) {
    case PLAN_ACTIVATION_START:
      break;
    case PLAN_ACTIVATION_DELAY_OTASP: {
      UMA_HISTOGRAM_COUNTS("Cellular.RetryOTASP", 1);
      BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
          base::Bind(&MobileActivator::RetryOTASP, AsWeakPtr()),
          base::TimeDelta::FromMilliseconds(kOTASPRetryDelay));
      break;
    }
    case PLAN_ACTIVATION_START_OTASP:
      break;
    case PLAN_ACTIVATION_INITIATING_ACTIVATION:
    case PLAN_ACTIVATION_TRYING_OTASP:
    case PLAN_ACTIVATION_OTASP: {
      DCHECK(network);
      network_handler::ErrorCallback on_activation_error =
          base::Bind(&MobileActivator::HandleActivationFailure, AsWeakPtr(),
                     network->path(),
                     new_state);
      RequestCellularActivation(
          network,
          base::Bind(&MobileActivator::StartOTASPTimer, AsWeakPtr()),
          on_activation_error);
      }
      break;
    case PLAN_ACTIVATION_PAGE_LOADING:
      return;
    case PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING:
    case PLAN_ACTIVATION_SHOWING_PAYMENT:
    case PLAN_ACTIVATION_RECONNECTING_PAYMENT:
      // Fix for fix SSL for the walled gardens where cert chain verification
      // might not work.
      break;
    case PLAN_ACTIVATION_WAITING_FOR_CONNECTION:
      post_reconnect_state_ = old_state;
      break;
    case PLAN_ACTIVATION_RECONNECTING: {
      PlanActivationState next_state = old_state;
      // Pick where we want to return to after we reconnect.
      switch (old_state) {
        case PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING:
        case PLAN_ACTIVATION_SHOWING_PAYMENT:
          // We decide here what to do next based on the state of the modem.
          next_state = PLAN_ACTIVATION_RECONNECTING_PAYMENT;
          break;
        case PLAN_ACTIVATION_INITIATING_ACTIVATION:
        case PLAN_ACTIVATION_TRYING_OTASP:
          next_state = PLAN_ACTIVATION_START;
          break;
        case PLAN_ACTIVATION_START_OTASP:
        case PLAN_ACTIVATION_OTASP:
          if (!network || !network->IsConnectedState()) {
            next_state = PLAN_ACTIVATION_START_OTASP;
          } else {
            // We're online, which means we've conspired with
            // PickNextOnlineState to reconnect after activation (that's the
            // only way we see this transition).  Thus, after we reconnect, we
            // should be done.
            next_state = PLAN_ACTIVATION_DONE;
          }
          break;
        default:
          LOG(ERROR) << "Transitioned to RECONNECTING from an unexpected "
                     << "state.";
          break;
      }
      if (network)
        ForceReconnect(network, next_state);
      break;
    }
    case PLAN_ACTIVATION_DONE:
      DCHECK(network);
      CompleteActivation();
      UMA_HISTOGRAM_COUNTS("Cellular.MobileSetupSucceeded", 1);
      break;
    case PLAN_ACTIVATION_ERROR:
      CompleteActivation();
      UMA_HISTOGRAM_COUNTS("Cellular.PlanFailed", 1);
      break;
    default:
      break;
  }
}

void MobileActivator::ReEnableCertRevocationChecking() {
  // Check that both the browser process and prefs exist before trying to
  // use them, since this method can be called by the destructor while Chrome
  // is shutting down, during which either could be NULL.
  if (!g_browser_process)
    return;
  PrefService* prefs = g_browser_process->local_state();
  if (!prefs)
    return;
  if (reenable_cert_check_) {
    prefs->SetBoolean(prefs::kCertRevocationCheckingEnabled, true);
    reenable_cert_check_ = false;
  }
}

void MobileActivator::DisableCertRevocationChecking() {
  // Disable SSL cert checks since we might be performing activation in the
  // restricted pool.
  // TODO(rkc): We want to do this only if on Cellular.
  PrefService* prefs = g_browser_process->local_state();
  if (!reenable_cert_check_ &&
      prefs->GetBoolean(prefs::kCertRevocationCheckingEnabled)) {
    reenable_cert_check_ = true;
    prefs->SetBoolean(prefs::kCertRevocationCheckingEnabled, false);
  }
}

bool MobileActivator::GotActivationError(
    const NetworkState* network, std::string* error) const {
  DCHECK(network);
  bool got_error = false;
  const char* error_code = kErrorDefault;
  const std::string& activation = network->activation_state();

  // This is the magic for detection of errors in during activation process.
  if (network->connection_state() == shill::kStateFailure &&
      network->error() == shill::kErrorAaaFailed) {
    if (activation == shill::kActivationStatePartiallyActivated) {
      error_code = kErrorBadConnectionPartial;
    } else if (activation == shill::kActivationStateActivated) {
      if (network->roaming() == shill::kRoamingStateHome)
        error_code = kErrorBadConnectionActivated;
      else if (network->roaming() == shill::kRoamingStateRoaming)
        error_code = kErrorRoamingOnConnection;
    }
    got_error = true;
  } else if (network->connection_state() == shill::kStateActivationFailure) {
    if (network->error() == shill::kErrorNeedEvdo) {
      if (activation == shill::kActivationStatePartiallyActivated)
        error_code = kErrorNoEVDO;
    } else if (network->error() == shill::kErrorNeedHomeNetwork) {
      if (activation == shill::kActivationStateNotActivated) {
        error_code = kErrorRoamingActivation;
      } else if (activation == shill::kActivationStatePartiallyActivated) {
        error_code = kErrorRoamingPartiallyActivated;
      }
    }
    got_error = true;
  }

  if (got_error)
    *error = GetErrorMessage(error_code);

  return got_error;
}

std::string MobileActivator::GetErrorMessage(const std::string& code) const {
  return cellular_config_->GetErrorMessage(code);
}

void MobileActivator::SignalCellularPlanPayment() {
  DCHECK(!HasRecentCellularPlanPayment());
  cellular_plan_payment_time_ = base::Time::Now();
}

bool MobileActivator::HasRecentCellularPlanPayment() const {
  const int kRecentPlanPaymentHours = 6;
  return (base::Time::Now() -
          cellular_plan_payment_time_).InHours() < kRecentPlanPaymentHours;
}

}  // namespace chromeos
