Home | History | Annotate | Download | only in chromeos
      1 // Copyright (c) 2011 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/ui/webui/chromeos/mobile_setup_ui.h"
      6 
      7 #include <algorithm>
      8 #include <map>
      9 #include <string>
     10 
     11 #include "base/callback.h"
     12 #include "base/file_util.h"
     13 #include "base/json/json_reader.h"
     14 #include "base/json/json_writer.h"
     15 #include "base/logging.h"
     16 #include "base/memory/weak_ptr.h"
     17 #include "base/metrics/histogram.h"
     18 #include "base/string_piece.h"
     19 #include "base/string_util.h"
     20 #include "base/threading/thread_restrictions.h"
     21 #include "base/timer.h"
     22 #include "base/utf_string_conversions.h"
     23 #include "base/values.h"
     24 #include "chrome/browser/browser_process.h"
     25 #include "chrome/browser/chromeos/cros/cros_library.h"
     26 #include "chrome/browser/chromeos/cros/network_library.h"
     27 #include "chrome/browser/prefs/pref_service.h"
     28 #include "chrome/browser/profiles/profile.h"
     29 #include "chrome/browser/ui/browser_list.h"
     30 #include "chrome/browser/ui/webui/chrome_url_data_manager.h"
     31 #include "chrome/common/jstemplate_builder.h"
     32 #include "chrome/common/pref_names.h"
     33 #include "chrome/common/url_constants.h"
     34 #include "content/browser/browser_thread.h"
     35 #include "content/browser/tab_contents/tab_contents.h"
     36 #include "googleurl/src/gurl.h"
     37 #include "grit/browser_resources.h"
     38 #include "grit/chromium_strings.h"
     39 #include "grit/generated_resources.h"
     40 #include "grit/locale_settings.h"
     41 #include "ui/base/l10n/l10n_util.h"
     42 #include "ui/base/resource/resource_bundle.h"
     43 
     44 namespace {
     45 
     46 // Host page JS API function names.
     47 const char kJsApiStartActivation[] = "startActivation";
     48 const char kJsApiSetTransactionStatus[] = "setTransactionStatus";
     49 
     50 const char kJsDeviceStatusChangedHandler[] =
     51     "mobile.MobileSetup.deviceStateChanged";
     52 
     53 // Error codes matching codes defined in the cellular config file.
     54 const char kErrorDefault[] = "default";
     55 const char kErrorBadConnectionPartial[] = "bad_connection_partial";
     56 const char kErrorBadConnectionActivated[] = "bad_connection_activated";
     57 const char kErrorRoamingOnConnection[] = "roaming_connection";
     58 const char kErrorNoEVDO[] = "no_evdo";
     59 const char kErrorRoamingActivation[] = "roaming_activation";
     60 const char kErrorRoamingPartiallyActivated[] = "roaming_partially_activated";
     61 const char kErrorNoService[] = "no_service";
     62 const char kErrorDisabled[] = "disabled";
     63 const char kErrorNoDevice[] = "no_device";
     64 const char kFailedPaymentError[] = "failed_payment";
     65 const char kFailedConnectivity[] = "connectivity";
     66 const char kErrorAlreadyRunning[] = "already_running";
     67 
     68 // Cellular configuration file path.
     69 const char kCellularConfigPath[] =
     70     "/usr/share/chromeos-assets/mobile/mobile_config.json";
     71 
     72 // Cellular config file field names.
     73 const char kVersionField[] = "version";
     74 const char kErrorsField[] = "errors";
     75 
     76 // Number of times we will retry to restart the activation process in case
     77 // there is no connectivity in the restricted pool.
     78 const int kMaxActivationAttempt = 3;
     79 // Number of times we will retry to reconnect if connection fails.
     80 const int kMaxConnectionRetry = 10;
     81 // Number of times we will retry to reconnect if connection fails.
     82 const int kMaxConnectionRetryOTASP = 30;
     83 // Number of times we will retry to reconnect after payment is processed.
     84 const int kMaxReconnectAttemptOTASP = 30;
     85 // Reconnect retry delay (after payment is processed).
     86 const int kPostPaymentReconnectDelayMS = 30000;   // 30s.
     87 // Connection timeout in seconds.
     88 const int kConnectionTimeoutSeconds = 45;
     89 // Reconnect delay.
     90 const int kReconnectDelayMS = 3000;
     91 // Reconnect timer delay.
     92 const int kReconnectTimerDelayMS = 5000;
     93 // Reconnect delay after previous failure.
     94 const int kFailedReconnectDelayMS = 10000;
     95 // Retry delay after failed OTASP attempt.
     96 const int kOTASPRetryDelay = 20000;
     97 
     98 chromeos::CellularNetwork* GetCellularNetwork() {
     99   chromeos::NetworkLibrary* lib = chromeos::CrosLibrary::Get()->
    100       GetNetworkLibrary();
    101   if (lib->cellular_networks().begin() != lib->cellular_networks().end()) {
    102     return *(lib->cellular_networks().begin());
    103   }
    104   return NULL;
    105 }
    106 
    107 chromeos::CellularNetwork* GetCellularNetwork(
    108     const std::string& service_path) {
    109   return chromeos::CrosLibrary::Get()->
    110       GetNetworkLibrary()->FindCellularNetworkByPath(service_path);
    111 }
    112 
    113 }  // namespace
    114 
    115 class CellularConfigDocument {
    116  public:
    117   CellularConfigDocument() {}
    118 
    119   // Return error message for a given code.
    120   std::string GetErrorMessage(const std::string& code);
    121   const std::string& version() { return version_; }
    122 
    123   bool LoadFromFile(const FilePath& config_path);
    124 
    125  private:
    126   std::string version_;
    127   std::map<std::string, std::string> error_map_;
    128 
    129   DISALLOW_COPY_AND_ASSIGN(CellularConfigDocument);
    130 };
    131 
    132 static std::map<std::string, std::string> error_messages_;
    133 
    134 class MobileSetupUIHTMLSource : public ChromeURLDataManager::DataSource {
    135  public:
    136   explicit MobileSetupUIHTMLSource(const std::string& service_path);
    137 
    138   // Called when the network layer has requested a resource underneath
    139   // the path we registered.
    140   virtual void StartDataRequest(const std::string& path,
    141                                 bool is_incognito,
    142                                 int request_id);
    143   virtual std::string GetMimeType(const std::string&) const {
    144     return "text/html";
    145   }
    146 
    147  private:
    148   virtual ~MobileSetupUIHTMLSource() {}
    149 
    150   std::string service_path_;
    151   DISALLOW_COPY_AND_ASSIGN(MobileSetupUIHTMLSource);
    152 };
    153 
    154 // The handler for Javascript messages related to the "register" view.
    155 class MobileSetupHandler
    156   : public WebUIMessageHandler,
    157     public chromeos::NetworkLibrary::NetworkManagerObserver,
    158     public chromeos::NetworkLibrary::NetworkObserver,
    159     public base::SupportsWeakPtr<MobileSetupHandler> {
    160  public:
    161   explicit MobileSetupHandler(const std::string& service_path);
    162   virtual ~MobileSetupHandler();
    163 
    164   // Init work after Attach.
    165   void Init(TabContents* contents);
    166 
    167   // WebUIMessageHandler implementation.
    168   virtual WebUIMessageHandler* Attach(WebUI* web_ui);
    169   virtual void RegisterMessages();
    170 
    171   // NetworkLibrary::NetworkManagerObserver implementation.
    172   virtual void OnNetworkManagerChanged(chromeos::NetworkLibrary* obj);
    173   // NetworkLibrary::NetworkObserver implementation.
    174   virtual void OnNetworkChanged(chromeos::NetworkLibrary* obj,
    175                                 const chromeos::Network* network);
    176 
    177  private:
    178   typedef enum PlanActivationState {
    179     PLAN_ACTIVATION_PAGE_LOADING            = -1,
    180     PLAN_ACTIVATION_START                   = 0,
    181     PLAN_ACTIVATION_TRYING_OTASP            = 1,
    182     PLAN_ACTIVATION_RECONNECTING_OTASP_TRY  = 2,
    183     PLAN_ACTIVATION_INITIATING_ACTIVATION   = 3,
    184     PLAN_ACTIVATION_RECONNECTING            = 4,
    185     PLAN_ACTIVATION_SHOWING_PAYMENT         = 5,
    186     PLAN_ACTIVATION_DELAY_OTASP             = 6,
    187     PLAN_ACTIVATION_START_OTASP             = 7,
    188     PLAN_ACTIVATION_OTASP                   = 8,
    189     PLAN_ACTIVATION_RECONNECTING_OTASP      = 9,
    190     PLAN_ACTIVATION_DONE                    = 10,
    191     PLAN_ACTIVATION_ERROR                   = 0xFF,
    192   } PlanActivationState;
    193 
    194   class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> {
    195    public:
    196     TaskProxy(const base::WeakPtr<MobileSetupHandler>& handler, int delay)
    197         : handler_(handler), delay_(delay) {
    198     }
    199     TaskProxy(const base::WeakPtr<MobileSetupHandler>& handler,
    200               const std::string& status)
    201         : handler_(handler), status_(status) {
    202     }
    203     void HandleStartActivation() {
    204       if (handler_)
    205         handler_->StartActivation();
    206     }
    207     void HandleSetTransactionStatus() {
    208       if (handler_)
    209         handler_->SetTransactionStatus(status_);
    210     }
    211     void ContinueConnecting() {
    212       if (handler_)
    213         handler_->ContinueConnecting(delay_);
    214     }
    215     void RetryOTASP() {
    216       if (handler_)
    217         handler_->RetryOTASP();
    218     }
    219    private:
    220     base::WeakPtr<MobileSetupHandler> handler_;
    221     std::string status_;
    222     int delay_;
    223     DISALLOW_COPY_AND_ASSIGN(TaskProxy);
    224   };
    225 
    226   // Handlers for JS WebUI messages.
    227   void HandleSetTransactionStatus(const ListValue* args);
    228   void HandleStartActivation(const ListValue* args);
    229   void SetTransactionStatus(const std::string& status);
    230   // Schedules activation process via task proxy.
    231   void InitiateActivation();
    232   // Starts activation.
    233   void StartActivation();
    234   // Retried OTASP.
    235   void RetryOTASP();
    236   // Continues activation process. This method is called after we disconnect
    237   // due to detected connectivity issue to kick off reconnection.
    238   void ContinueConnecting(int delay);
    239 
    240   // Sends message to host registration page with system/user info data.
    241   void SendDeviceInfo();
    242 
    243   // Callback for when |reconnect_timer_| fires.
    244   void ReconnectTimerFired();
    245   // Starts OTASP process.
    246   void StartOTASP();
    247   // Checks if we need to reconnect due to failed connection attempt.
    248   bool NeedsReconnecting(chromeos::CellularNetwork* network,
    249                          PlanActivationState* new_state,
    250                          std::string* error_description);
    251   // Disconnect from network.
    252   void DisconnectFromNetwork(chromeos::CellularNetwork* network);
    253   // Connects to cellular network, resets connection timer.
    254   bool ConnectToNetwork(chromeos::CellularNetwork* network, int delay);
    255   // Forces disconnect / reconnect when we detect portal connectivity issues.
    256   void ForceReconnect(chromeos::CellularNetwork* network, int delay);
    257   // Reports connection timeout.
    258   bool ConnectionTimeout();
    259   // Verify the state of cellular network and modify internal state.
    260   void EvaluateCellularNetwork(chromeos::CellularNetwork* network);
    261   // Check the current cellular network for error conditions.
    262   bool GotActivationError(chromeos::CellularNetwork* network,
    263                           std::string* error);
    264   // Sends status updates to WebUI page.
    265   void UpdatePage(chromeos::CellularNetwork* network,
    266                   const std::string& error_description);
    267   // Changes internal state.
    268   void ChangeState(chromeos::CellularNetwork* network,
    269                    PlanActivationState new_state,
    270                    const std::string& error_description);
    271   // Prepares network devices for cellular activation process.
    272   void SetupActivationProcess(chromeos::CellularNetwork* network);
    273   // Disables ethernet and wifi newtorks since they interefere with
    274   // detection of restricted pool on cellular side.
    275   void DisableOtherNetworks();
    276   // Resets network devices after cellular activation process.
    277   // |network| should be NULL if the activation process failed.
    278   void CompleteActivation(chromeos::CellularNetwork* network);
    279   // Control routines for handling other types of connections during
    280   // cellular activation.
    281   void ReEnableOtherConnections();
    282 
    283   // Converts the currently active CellularNetwork device into a JS object.
    284   static void GetDeviceInfo(chromeos::CellularNetwork* network,
    285                             DictionaryValue* value);
    286   static bool ShouldReportDeviceState(std::string* state, std::string* error);
    287 
    288   // Performs activation state cellular device evaluation.
    289   // Returns false if device activation failed. In this case |error|
    290   // will contain error message to be reported to Web UI.
    291   static bool EvaluateCellularDeviceState(bool* report_status,
    292                                           std::string* state,
    293                                           std::string* error);
    294 
    295   // Return error message for a given code.
    296   static std::string GetErrorMessage(const std::string& code);
    297   static void LoadCellularConfig();
    298 
    299   // Returns next reconnection state based on the current activation phase.
    300   static PlanActivationState GetNextReconnectState(PlanActivationState state);
    301   static const char* GetStateDescription(PlanActivationState state);
    302 
    303   static scoped_ptr<CellularConfigDocument> cellular_config_;
    304 
    305   TabContents* tab_contents_;
    306   // Internal handler state.
    307   PlanActivationState state_;
    308   std::string service_path_;
    309   // Flags that control if wifi and ethernet connection needs to be restored
    310   // after the activation of cellular network.
    311   bool reenable_wifi_;
    312   bool reenable_ethernet_;
    313   bool reenable_cert_check_;
    314   bool evaluating_;
    315   // True if we think that another tab is already running activation.
    316   bool already_running_;
    317   // Connection retry counter.
    318   int connection_retry_count_;
    319   // Post payment reconnect wait counters.
    320   int reconnect_wait_count_;
    321   // Activation retry attempt count;
    322   int activation_attempt_;
    323   // Connection start time.
    324   base::Time connection_start_time_;
    325   // Timer that monitors reconnection timeouts.
    326   base::RepeatingTimer<MobileSetupHandler> reconnect_timer_;
    327 
    328   DISALLOW_COPY_AND_ASSIGN(MobileSetupHandler);
    329 };
    330 
    331 scoped_ptr<CellularConfigDocument> MobileSetupHandler::cellular_config_;
    332 
    333 ////////////////////////////////////////////////////////////////////////////////
    334 //
    335 // CellularConfigDocument
    336 //
    337 ////////////////////////////////////////////////////////////////////////////////
    338 
    339 std::string CellularConfigDocument::GetErrorMessage(const std::string& code) {
    340   std::map<std::string, std::string>::iterator iter = error_map_.find(code);
    341   if (iter == error_map_.end())
    342     return code;
    343   return iter->second;
    344 }
    345 
    346 bool CellularConfigDocument::LoadFromFile(const FilePath& config_path) {
    347   error_map_.clear();
    348 
    349   std::string config;
    350   {
    351     // Reading config file causes us to do blocking IO on UI thread.
    352     // Temporarily allow it until we fix http://crosbug.com/11535
    353     base::ThreadRestrictions::ScopedAllowIO allow_io;
    354     if (!file_util::ReadFileToString(config_path, &config))
    355       return false;
    356   }
    357 
    358   scoped_ptr<Value> root(base::JSONReader::Read(config, true));
    359   DCHECK(root.get() != NULL);
    360   if (!root.get() || root->GetType() != Value::TYPE_DICTIONARY) {
    361     LOG(WARNING) << "Bad cellular config file";
    362     return false;
    363   }
    364 
    365   DictionaryValue* root_dict = static_cast<DictionaryValue*>(root.get());
    366   if (!root_dict->GetString(kVersionField, &version_)) {
    367     LOG(WARNING) << "Cellular config file missing version";
    368     return false;
    369   }
    370   DictionaryValue* errors = NULL;
    371   if (!root_dict->GetDictionary(kErrorsField, &errors))
    372     return false;
    373   for (DictionaryValue::key_iterator keys = errors->begin_keys();
    374        keys != errors->end_keys();
    375        ++keys) {
    376     std::string value;
    377     if (!errors->GetString(*keys, &value)) {
    378       LOG(WARNING) << "Bad cellular config error value";
    379       error_map_.clear();
    380       return false;
    381     }
    382 
    383     error_map_.insert(std::pair<std::string, std::string>(*keys, value));
    384   }
    385   return true;
    386 }
    387 
    388 ////////////////////////////////////////////////////////////////////////////////
    389 //
    390 // MobileSetupUIHTMLSource
    391 //
    392 ////////////////////////////////////////////////////////////////////////////////
    393 
    394 MobileSetupUIHTMLSource::MobileSetupUIHTMLSource(
    395     const std::string& service_path)
    396     : DataSource(chrome::kChromeUIMobileSetupHost, MessageLoop::current()),
    397       service_path_(service_path) {
    398 }
    399 
    400 void MobileSetupUIHTMLSource::StartDataRequest(const std::string& path,
    401                                                bool is_incognito,
    402                                                int request_id) {
    403   chromeos::CellularNetwork* network = GetCellularNetwork(service_path_);
    404   DCHECK(network);
    405   DictionaryValue strings;
    406   strings.SetString("title", l10n_util::GetStringUTF16(IDS_MOBILE_SETUP_TITLE));
    407   strings.SetString("connecting_header",
    408                     l10n_util::GetStringFUTF16(IDS_MOBILE_CONNECTING_HEADER,
    409                         network ? UTF8ToUTF16(network->name()) : string16()));
    410   strings.SetString("error_header",
    411                     l10n_util::GetStringUTF16(IDS_MOBILE_ERROR_HEADER));
    412   strings.SetString("activating_header",
    413                     l10n_util::GetStringUTF16(IDS_MOBILE_ACTIVATING_HEADER));
    414   strings.SetString("completed_header",
    415                     l10n_util::GetStringUTF16(IDS_MOBILE_COMPLETED_HEADER));
    416   strings.SetString("please_wait",
    417                     l10n_util::GetStringUTF16(IDS_MOBILE_PLEASE_WAIT));
    418   strings.SetString("completed_text",
    419                     l10n_util::GetStringUTF16(IDS_MOBILE_COMPLETED_TEXT));
    420   strings.SetString("close_button",
    421                     l10n_util::GetStringUTF16(IDS_CLOSE));
    422   SetFontAndTextDirection(&strings);
    423 
    424   static const base::StringPiece html(
    425       ResourceBundle::GetSharedInstance().GetRawDataResource(
    426           IDR_MOBILE_SETUP_PAGE_HTML));
    427 
    428   const std::string full_html = jstemplate_builder::GetI18nTemplateHtml(
    429       html, &strings);
    430 
    431   scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
    432   html_bytes->data.resize(full_html.size());
    433   std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin());
    434 
    435   SendResponse(request_id, html_bytes);
    436 }
    437 
    438 ////////////////////////////////////////////////////////////////////////////////
    439 //
    440 // MobileSetupHandler
    441 //
    442 ////////////////////////////////////////////////////////////////////////////////
    443 MobileSetupHandler::MobileSetupHandler(const std::string& service_path)
    444     : tab_contents_(NULL),
    445       state_(PLAN_ACTIVATION_PAGE_LOADING),
    446       service_path_(service_path),
    447       reenable_wifi_(false),
    448       reenable_ethernet_(false),
    449       reenable_cert_check_(false),
    450       evaluating_(false),
    451       already_running_(false),
    452       connection_retry_count_(0),
    453       reconnect_wait_count_(0),
    454       activation_attempt_(0) {
    455 }
    456 
    457 MobileSetupHandler::~MobileSetupHandler() {
    458   reconnect_timer_.Stop();
    459   chromeos::NetworkLibrary* lib =
    460       chromeos::CrosLibrary::Get()->GetNetworkLibrary();
    461   lib->RemoveNetworkManagerObserver(this);
    462   lib->RemoveObserverForAllNetworks(this);
    463   if (lib->IsLocked())
    464     lib->Unlock();
    465   ReEnableOtherConnections();
    466 }
    467 
    468 WebUIMessageHandler* MobileSetupHandler::Attach(WebUI* web_ui) {
    469   return WebUIMessageHandler::Attach(web_ui);
    470 }
    471 
    472 void MobileSetupHandler::Init(TabContents* contents) {
    473   tab_contents_ = contents;
    474   LoadCellularConfig();
    475   if (!chromeos::CrosLibrary::Get()->GetNetworkLibrary()->IsLocked())
    476     SetupActivationProcess(GetCellularNetwork(service_path_));
    477   else
    478     already_running_ = true;
    479 }
    480 
    481 void MobileSetupHandler::RegisterMessages() {
    482   web_ui_->RegisterMessageCallback(kJsApiStartActivation,
    483       NewCallback(this, &MobileSetupHandler::HandleStartActivation));
    484   web_ui_->RegisterMessageCallback(kJsApiSetTransactionStatus,
    485       NewCallback(this, &MobileSetupHandler::HandleSetTransactionStatus));
    486 }
    487 
    488 void MobileSetupHandler::OnNetworkManagerChanged(
    489     chromeos::NetworkLibrary* cros) {
    490   if (state_ == PLAN_ACTIVATION_PAGE_LOADING)
    491     return;
    492   // Note that even though we get here when the service has
    493   // reappeared after disappearing earlier in the activation
    494   // process, there's no need to re-establish the NetworkObserver,
    495   // because the service path remains the same.
    496   EvaluateCellularNetwork(GetCellularNetwork(service_path_));
    497 }
    498 
    499 void MobileSetupHandler::OnNetworkChanged(chromeos::NetworkLibrary* cros,
    500                                           const chromeos::Network* network) {
    501   if (state_ == PLAN_ACTIVATION_PAGE_LOADING)
    502     return;
    503   DCHECK(network && network->type() == chromeos::TYPE_CELLULAR);
    504   EvaluateCellularNetwork(GetCellularNetwork(network->service_path()));
    505 }
    506 
    507 void MobileSetupHandler::HandleStartActivation(const ListValue* args) {
    508   InitiateActivation();
    509   UMA_HISTOGRAM_COUNTS("Cellular.MobileSetupStart", 1);
    510 }
    511 
    512 void MobileSetupHandler::HandleSetTransactionStatus(const ListValue* args) {
    513   const size_t kSetTransactionStatusParamCount = 1;
    514   if (args->GetSize() != kSetTransactionStatusParamCount)
    515     return;
    516   // Get change callback function name.
    517   std::string status;
    518   if (!args->GetString(0, &status))
    519     return;
    520   scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), status);
    521   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    522       NewRunnableMethod(task.get(), &TaskProxy::HandleSetTransactionStatus));
    523 }
    524 
    525 void MobileSetupHandler::InitiateActivation() {
    526   scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), 0);
    527   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    528       NewRunnableMethod(task.get(), &TaskProxy::HandleStartActivation));
    529 }
    530 
    531 void MobileSetupHandler::StartActivation() {
    532   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    533   chromeos::NetworkLibrary* lib =
    534       chromeos::CrosLibrary::Get()->GetNetworkLibrary();
    535   chromeos::CellularNetwork* network = GetCellularNetwork(service_path_);
    536   // Check if we can start activation process.
    537   if (!network || already_running_) {
    538     std::string error;
    539     if (already_running_)
    540       error = kErrorAlreadyRunning;
    541     else if (!lib->cellular_available())
    542       error = kErrorNoDevice;
    543     else if (!lib->cellular_enabled())
    544       error = kErrorDisabled;
    545     else
    546       error = kErrorNoService;
    547     ChangeState(NULL, PLAN_ACTIVATION_ERROR, GetErrorMessage(error));
    548     return;
    549   }
    550 
    551   // Start monitoring network property changes.
    552   lib->AddNetworkManagerObserver(this);
    553   lib->RemoveObserverForAllNetworks(this);
    554   lib->AddNetworkObserver(network->service_path(), this);
    555   // Try to start with OTASP immediately if we have received payment recently.
    556   state_ = lib->HasRecentCellularPlanPayment() ?
    557                PLAN_ACTIVATION_START_OTASP :
    558                PLAN_ACTIVATION_START;
    559   EvaluateCellularNetwork(network);
    560 }
    561 
    562 void MobileSetupHandler::RetryOTASP() {
    563   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    564   DCHECK(state_ == PLAN_ACTIVATION_DELAY_OTASP);
    565   StartOTASP();
    566 }
    567 
    568 void MobileSetupHandler::ContinueConnecting(int delay) {
    569   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    570   chromeos::CellularNetwork* network = GetCellularNetwork(service_path_);
    571   if (network && network->connecting_or_connected()) {
    572     EvaluateCellularNetwork(network);
    573   } else {
    574     ConnectToNetwork(network, delay);
    575   }
    576 }
    577 
    578 void MobileSetupHandler::SetTransactionStatus(const std::string& status) {
    579   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    580   // The payment is received, try to reconnect and check the status all over
    581   // again.
    582   if (LowerCaseEqualsASCII(status, "ok") &&
    583       state_ == PLAN_ACTIVATION_SHOWING_PAYMENT) {
    584     chromeos::NetworkLibrary* lib =
    585         chromeos::CrosLibrary::Get()->GetNetworkLibrary();
    586     lib->SignalCellularPlanPayment();
    587     UMA_HISTOGRAM_COUNTS("Cellular.PaymentReceived", 1);
    588     StartOTASP();
    589   } else {
    590     UMA_HISTOGRAM_COUNTS("Cellular.PaymentFailed", 1);
    591   }
    592 }
    593 
    594 void MobileSetupHandler::StartOTASP() {
    595   state_ = PLAN_ACTIVATION_START_OTASP;
    596   chromeos::CellularNetwork* network = GetCellularNetwork();
    597   if (network &&
    598       network->connected() &&
    599       network->activation_state() == chromeos::ACTIVATION_STATE_ACTIVATED) {
    600     chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
    601         DisconnectFromNetwork(network);
    602   } else {
    603     EvaluateCellularNetwork(network);
    604   }
    605 }
    606 
    607 void MobileSetupHandler::ReconnectTimerFired() {
    608   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    609   // Permit network connection changes only in reconnecting states.
    610   if (state_ != PLAN_ACTIVATION_RECONNECTING_OTASP_TRY &&
    611       state_ != PLAN_ACTIVATION_RECONNECTING &&
    612       state_ != PLAN_ACTIVATION_RECONNECTING_OTASP)
    613     return;
    614   chromeos::CellularNetwork* network = GetCellularNetwork(service_path_);
    615   if (!network) {
    616     // No service, try again since this is probably just transient condition.
    617     LOG(WARNING) << "Service not present at reconnect attempt.";
    618   }
    619   EvaluateCellularNetwork(network);
    620 }
    621 
    622 void MobileSetupHandler::DisconnectFromNetwork(
    623     chromeos::CellularNetwork* network) {
    624   DCHECK(network);
    625   LOG(INFO) << "Disconnecting from: " << network->service_path();
    626   chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
    627       DisconnectFromNetwork(network);
    628   // Disconnect will force networks to be reevaluated, so
    629   // we don't want to continue processing on this path anymore.
    630   evaluating_ = false;
    631 }
    632 
    633 bool MobileSetupHandler::NeedsReconnecting(
    634     chromeos::CellularNetwork* network,
    635     PlanActivationState* new_state,
    636     std::string* error_description) {
    637   DCHECK(network);
    638   if (!network->failed() && !ConnectionTimeout())
    639     return false;
    640 
    641   // Try to reconnect again if reconnect failed, or if for some
    642   // reasons we are still not connected after 45 seconds.
    643   int max_retries = (state_ == PLAN_ACTIVATION_RECONNECTING_OTASP) ?
    644                         kMaxConnectionRetryOTASP : kMaxConnectionRetry;
    645   if (connection_retry_count_ < max_retries) {
    646     UMA_HISTOGRAM_COUNTS("Cellular.ConnectionRetry", 1);
    647     ConnectToNetwork(network, kFailedReconnectDelayMS);
    648     return true;
    649   }
    650   // We simply can't connect anymore after all these tries.
    651   UMA_HISTOGRAM_COUNTS("Cellular.ConnectionFailed", 1);
    652   *new_state = PLAN_ACTIVATION_ERROR;
    653   *error_description = GetErrorMessage(kFailedConnectivity);
    654   return false;
    655 }
    656 
    657 bool MobileSetupHandler::ConnectToNetwork(
    658     chromeos::CellularNetwork* network,
    659     int delay) {
    660   if (network && network->connecting_or_connected())
    661     return true;
    662   // Permit network connection changes only in reconnecting states.
    663   if (state_ != PLAN_ACTIVATION_RECONNECTING_OTASP_TRY &&
    664       state_ != PLAN_ACTIVATION_RECONNECTING &&
    665       state_ != PLAN_ACTIVATION_RECONNECTING_OTASP)
    666     return false;
    667   if (network)
    668     LOG(INFO) << "Connecting to: " << network->service_path();
    669   connection_retry_count_++;
    670   connection_start_time_ = base::Time::Now();
    671   if (!network) {
    672     LOG(WARNING) << "Connect failed."
    673                  << (network ? network->service_path().c_str() : "no service");
    674     // If we coudn't connect during reconnection phase, try to reconnect
    675     // with a delay (and try to reconnect if needed).
    676     scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(),
    677                                                   delay);
    678     BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
    679         NewRunnableMethod(task.get(), &TaskProxy::ContinueConnecting),
    680         delay);
    681     return false;
    682   }
    683   chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
    684       ConnectToCellularNetwork(network);
    685   return true;
    686 }
    687 
    688 void MobileSetupHandler::ForceReconnect(
    689     chromeos::CellularNetwork* network,
    690     int delay) {
    691   DCHECK(network);
    692   UMA_HISTOGRAM_COUNTS("Cellular.ActivationRetry", 1);
    693   // Reset reconnect metrics.
    694   connection_retry_count_ = 0;
    695   connection_start_time_ = base::Time();
    696   // First, disconnect...
    697   LOG(INFO) << "Disconnecting from " << network->service_path();
    698   chromeos::CrosLibrary::Get()->GetNetworkLibrary()->
    699       DisconnectFromNetwork(network);
    700   // Check the network state 3s after we disconnect to make sure.
    701   scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(),
    702                                                 delay);
    703   BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
    704       NewRunnableMethod(task.get(), &TaskProxy::ContinueConnecting),
    705       delay);
    706 }
    707 
    708 bool MobileSetupHandler::ConnectionTimeout() {
    709   return (base::Time::Now() -
    710             connection_start_time_).InSeconds() > kConnectionTimeoutSeconds;
    711 }
    712 
    713 void MobileSetupHandler::EvaluateCellularNetwork(
    714     chromeos::CellularNetwork* network) {
    715   if (!web_ui_)
    716     return;
    717 
    718   PlanActivationState new_state = state_;
    719   if (!network) {
    720     LOG(WARNING) << "Cellular service lost";
    721     if (state_ == PLAN_ACTIVATION_RECONNECTING_OTASP_TRY ||
    722         state_ == PLAN_ACTIVATION_RECONNECTING ||
    723         state_ == PLAN_ACTIVATION_RECONNECTING_OTASP) {
    724       // This might be the legit case when service is lost after activation.
    725       // We need to make sure we force reconnection as soon as it shows up.
    726       LOG(INFO) << "Force service reconnection";
    727       connection_start_time_ = base::Time();
    728     }
    729     return;
    730   }
    731 
    732   // Prevent this method from being called if it is already on the stack.
    733   // This might happen on some state transitions (ie. connect, disconnect).
    734   if (evaluating_)
    735     return;
    736   evaluating_ = true;
    737   std::string error_description;
    738 
    739   LOG(WARNING) << "Cellular:\n  service=" << network->GetStateString().c_str()
    740       << "\n  ui=" << GetStateDescription(state_)
    741       << "\n  activation=" << network->GetActivationStateString().c_str()
    742       << "\n  connectivity="
    743       << network->GetConnectivityStateString().c_str()
    744       << "\n  error=" << network->GetErrorString().c_str()
    745       << "\n  setvice_path=" << network->service_path().c_str();
    746   switch (state_) {
    747     case PLAN_ACTIVATION_START: {
    748       switch (network->activation_state()) {
    749         case chromeos::ACTIVATION_STATE_ACTIVATED: {
    750           if (network->failed_or_disconnected()) {
    751             new_state = PLAN_ACTIVATION_RECONNECTING;
    752           } else if (network->connected()) {
    753             if (network->restricted_pool()) {
    754               new_state = PLAN_ACTIVATION_SHOWING_PAYMENT;
    755             } else {
    756               new_state = PLAN_ACTIVATION_DONE;
    757             }
    758           }
    759           break;
    760         }
    761         default: {
    762           if (network->failed_or_disconnected() ||
    763               network->state() == chromeos::STATE_ACTIVATION_FAILURE) {
    764             new_state = (network->activation_state() ==
    765                          chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED) ?
    766                             PLAN_ACTIVATION_TRYING_OTASP :
    767                             PLAN_ACTIVATION_INITIATING_ACTIVATION;
    768           } else if (network->connected()) {
    769             DisconnectFromNetwork(network);
    770             return;
    771           }
    772           break;
    773         }
    774       }
    775       break;
    776     }
    777     case PLAN_ACTIVATION_START_OTASP: {
    778       switch (network->activation_state()) {
    779         case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED: {
    780           if (network->failed_or_disconnected()) {
    781             new_state = PLAN_ACTIVATION_OTASP;
    782           } else if (network->connected()) {
    783             DisconnectFromNetwork(network);
    784             return;
    785           }
    786           break;
    787         }
    788         case chromeos::ACTIVATION_STATE_ACTIVATED:
    789           new_state = PLAN_ACTIVATION_RECONNECTING_OTASP;
    790           break;
    791         default: {
    792           LOG(WARNING) << "Unexpected activation state for device "
    793                        << network->service_path().c_str();
    794           break;
    795         }
    796       }
    797       break;
    798     }
    799     case PLAN_ACTIVATION_DELAY_OTASP:
    800       // Just ignore any changes until the OTASP retry timer kicks in.
    801       evaluating_ = false;
    802       return;
    803     case PLAN_ACTIVATION_INITIATING_ACTIVATION:
    804     case PLAN_ACTIVATION_OTASP:
    805     case PLAN_ACTIVATION_TRYING_OTASP: {
    806       switch (network->activation_state()) {
    807         case chromeos::ACTIVATION_STATE_ACTIVATED:
    808           if (network->failed_or_disconnected()) {
    809             new_state = GetNextReconnectState(state_);
    810           } else if (network->connected()) {
    811             if (network->restricted_pool()) {
    812               new_state = PLAN_ACTIVATION_SHOWING_PAYMENT;
    813             } else {
    814               new_state = PLAN_ACTIVATION_DONE;
    815             }
    816           }
    817           break;
    818         case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED:
    819           if (network->connected()) {
    820             if (network->restricted_pool())
    821               new_state = PLAN_ACTIVATION_SHOWING_PAYMENT;
    822           } else {
    823             new_state = GetNextReconnectState(state_);
    824           }
    825           break;
    826         case chromeos::ACTIVATION_STATE_NOT_ACTIVATED:
    827         case chromeos::ACTIVATION_STATE_ACTIVATING:
    828           // Wait in this state until activation state changes.
    829           break;
    830         default:
    831           break;
    832       }
    833       break;
    834     }
    835     case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY:
    836     case PLAN_ACTIVATION_RECONNECTING: {
    837       if (network->connected()) {
    838         // Make sure other networks are not interfering with our detection of
    839         // restricted pool.
    840         DisableOtherNetworks();
    841         // Wait until the service shows up and gets activated.
    842         switch (network->activation_state()) {
    843           case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED:
    844           case chromeos::ACTIVATION_STATE_ACTIVATED:
    845             if (network->connectivity_state() ==
    846                          chromeos::CONN_STATE_NONE) {
    847               LOG(WARNING) << "No connectivity for device "
    848                            << network->service_path().c_str();
    849               // If we are connected but there is no connectivity at all,
    850               // restart the whole process again.
    851               if (activation_attempt_ < kMaxActivationAttempt) {
    852                 activation_attempt_++;
    853                 LOG(WARNING) << "Reconnect attempt #"
    854                              << activation_attempt_;
    855                 ForceReconnect(network, kFailedReconnectDelayMS);
    856                 evaluating_ = false;
    857                 return;
    858               } else {
    859                 new_state = PLAN_ACTIVATION_ERROR;
    860                 UMA_HISTOGRAM_COUNTS("Cellular.ActivationRetryFailure", 1);
    861                 error_description = GetErrorMessage(kFailedConnectivity);
    862               }
    863             } else if (network->connectivity_state() ==
    864                            chromeos::CONN_STATE_RESTRICTED) {
    865               // If we have already received payment, don't show the payment
    866               // page again. We should try to reconnect after some time instead.
    867               new_state = PLAN_ACTIVATION_SHOWING_PAYMENT;
    868             } else if (network->activation_state() ==
    869                            chromeos::ACTIVATION_STATE_ACTIVATED) {
    870               new_state = PLAN_ACTIVATION_DONE;
    871             }
    872             break;
    873           default:
    874             break;
    875         }
    876       } else if (NeedsReconnecting(network, &new_state, &error_description)) {
    877         evaluating_ = false;
    878         return;
    879       }
    880       break;
    881     }
    882     case PLAN_ACTIVATION_RECONNECTING_OTASP: {
    883       if (network->connected()) {
    884         // Make sure other networks are not interfering with our detection of
    885         // restricted pool.
    886         DisableOtherNetworks();
    887         // Wait until the service shows up and gets activated.
    888         switch (network->activation_state()) {
    889           case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED:
    890           case chromeos::ACTIVATION_STATE_ACTIVATED:
    891             if (network->connectivity_state() == chromeos::CONN_STATE_NONE ||
    892                 network->connectivity_state() ==
    893                     chromeos::CONN_STATE_RESTRICTED) {
    894               LOG(WARNING) << "Still no connectivity after OTASP for device "
    895                            << network->service_path().c_str();
    896               // If we have already received payment, don't show the payment
    897               // page again. We should try to reconnect after some time instead.
    898               if (reconnect_wait_count_ < kMaxReconnectAttemptOTASP) {
    899                 reconnect_wait_count_++;
    900                 LOG(WARNING) << "OTASP reconnect attempt #"
    901                              << reconnect_wait_count_;
    902                 ForceReconnect(network, kPostPaymentReconnectDelayMS);
    903                 evaluating_ = false;
    904                 return;
    905               } else {
    906                 new_state = PLAN_ACTIVATION_ERROR;
    907                 UMA_HISTOGRAM_COUNTS("Cellular.PostPaymentConnectFailure", 1);
    908                 error_description = GetErrorMessage(kFailedConnectivity);
    909               }
    910             } else if (network->connectivity_state() ==
    911                            chromeos::CONN_STATE_UNRESTRICTED) {
    912               new_state = PLAN_ACTIVATION_DONE;
    913             }
    914             break;
    915           default:
    916             break;
    917         }
    918       } else if (NeedsReconnecting(network, &new_state, &error_description)) {
    919         evaluating_ = false;
    920         return;
    921       }
    922       break;
    923     }
    924     case PLAN_ACTIVATION_PAGE_LOADING:
    925       break;
    926     // Just ignore all signals until the site confirms payment.
    927     case PLAN_ACTIVATION_SHOWING_PAYMENT:
    928       // Activation completed/failed, ignore network changes.
    929     case PLAN_ACTIVATION_DONE:
    930     case PLAN_ACTIVATION_ERROR:
    931       break;
    932   }
    933 
    934   if (new_state != PLAN_ACTIVATION_ERROR &&
    935       GotActivationError(network, &error_description)) {
    936     // Check for this special case when we try to do activate partially
    937     // activated device. If that attempt failed, try to disconnect to clear the
    938     // state and reconnect again.
    939     if ((network->activation_state() ==
    940             chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED ||
    941         network->activation_state() == chromeos::ACTIVATION_STATE_ACTIVATING) &&
    942         (network->error() == chromeos::ERROR_NO_ERROR ||
    943             network->error() == chromeos::ERROR_OTASP_FAILED) &&
    944         network->state() == chromeos::STATE_ACTIVATION_FAILURE) {
    945       LOG(WARNING) << "Activation failure detected "
    946                    << network->service_path().c_str();
    947       switch (state_) {
    948         case PLAN_ACTIVATION_OTASP:
    949         case PLAN_ACTIVATION_RECONNECTING_OTASP:
    950           new_state = PLAN_ACTIVATION_DELAY_OTASP;
    951           break;
    952         case PLAN_ACTIVATION_TRYING_OTASP:
    953           new_state = PLAN_ACTIVATION_RECONNECTING_OTASP_TRY;
    954           break;
    955         case PLAN_ACTIVATION_INITIATING_ACTIVATION:
    956           new_state = PLAN_ACTIVATION_RECONNECTING;
    957           break;
    958         case PLAN_ACTIVATION_START:
    959           // We are just starting, so this must be previous activation attempt
    960           // failure.
    961           new_state = PLAN_ACTIVATION_TRYING_OTASP;
    962           break;
    963         case PLAN_ACTIVATION_DELAY_OTASP:
    964         case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY:
    965         case PLAN_ACTIVATION_RECONNECTING:
    966           new_state = state_;
    967           break;
    968         default:
    969           new_state = PLAN_ACTIVATION_ERROR;
    970           break;
    971       }
    972     } else {
    973       LOG(WARNING) << "Unexpected activation failure for "
    974                    << network->service_path().c_str();
    975       new_state = PLAN_ACTIVATION_ERROR;
    976     }
    977   }
    978 
    979   if (new_state == PLAN_ACTIVATION_ERROR && !error_description.length())
    980     error_description = GetErrorMessage(kErrorDefault);
    981 
    982   ChangeState(network, new_state, error_description);
    983   evaluating_ = false;
    984 }
    985 
    986 MobileSetupHandler::PlanActivationState
    987     MobileSetupHandler::GetNextReconnectState(
    988         MobileSetupHandler::PlanActivationState state) {
    989   switch (state) {
    990     case PLAN_ACTIVATION_INITIATING_ACTIVATION:
    991       return PLAN_ACTIVATION_RECONNECTING;
    992     case PLAN_ACTIVATION_OTASP:
    993       return PLAN_ACTIVATION_RECONNECTING_OTASP;
    994     case PLAN_ACTIVATION_TRYING_OTASP:
    995       return PLAN_ACTIVATION_RECONNECTING_OTASP_TRY;
    996     default:
    997       return PLAN_ACTIVATION_RECONNECTING;
    998   }
    999 }
   1000 
   1001 // Debugging helper function, will take it out at the end.
   1002 const char* MobileSetupHandler::GetStateDescription(
   1003     PlanActivationState state) {
   1004   switch (state) {
   1005     case PLAN_ACTIVATION_PAGE_LOADING:
   1006       return "PAGE_LOADING";
   1007     case PLAN_ACTIVATION_START:
   1008       return "ACTIVATION_START";
   1009     case PLAN_ACTIVATION_TRYING_OTASP:
   1010       return "TRYING_OTASP";
   1011     case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY:
   1012       return "RECONNECTING_OTASP_TRY";
   1013     case PLAN_ACTIVATION_INITIATING_ACTIVATION:
   1014       return "INITIATING_ACTIVATION";
   1015     case PLAN_ACTIVATION_RECONNECTING:
   1016       return "RECONNECTING";
   1017     case PLAN_ACTIVATION_SHOWING_PAYMENT:
   1018       return "SHOWING_PAYMENT";
   1019     case PLAN_ACTIVATION_START_OTASP:
   1020       return "START_OTASP";
   1021     case PLAN_ACTIVATION_DELAY_OTASP:
   1022       return "DELAY_OTASP";
   1023     case PLAN_ACTIVATION_OTASP:
   1024       return "OTASP";
   1025     case PLAN_ACTIVATION_RECONNECTING_OTASP:
   1026       return "RECONNECTING_OTASP";
   1027     case PLAN_ACTIVATION_DONE:
   1028       return "DONE";
   1029     case PLAN_ACTIVATION_ERROR:
   1030       return "ERROR";
   1031   }
   1032   return "UNKNOWN";
   1033 }
   1034 
   1035 
   1036 void MobileSetupHandler::CompleteActivation(
   1037     chromeos::CellularNetwork* network) {
   1038   // Remove observers, we are done with this page.
   1039   chromeos::NetworkLibrary* lib = chromeos::CrosLibrary::Get()->
   1040       GetNetworkLibrary();
   1041   lib->RemoveNetworkManagerObserver(this);
   1042   lib->RemoveObserverForAllNetworks(this);
   1043   if (lib->IsLocked())
   1044     lib->Unlock();
   1045   // If we have successfully activated the connection, set autoconnect flag.
   1046   if (network)
   1047     network->SetAutoConnect(true);
   1048   // Reactivate other types of connections if we have
   1049   // shut them down previously.
   1050   ReEnableOtherConnections();
   1051 }
   1052 
   1053 void MobileSetupHandler::UpdatePage(
   1054     chromeos::CellularNetwork* network,
   1055     const std::string& error_description) {
   1056   DictionaryValue device_dict;
   1057   if (network)
   1058     GetDeviceInfo(network, &device_dict);
   1059   device_dict.SetInteger("state", state_);
   1060   if (error_description.length())
   1061     device_dict.SetString("error", error_description);
   1062   web_ui_->CallJavascriptFunction(
   1063       kJsDeviceStatusChangedHandler, device_dict);
   1064 }
   1065 
   1066 
   1067 void MobileSetupHandler::ChangeState(chromeos::CellularNetwork* network,
   1068                                      PlanActivationState new_state,
   1069                                      const std::string& error_description) {
   1070   static bool first_time = true;
   1071   if (state_ == new_state && !first_time)
   1072     return;
   1073   LOG(WARNING) << "Activation state flip old = "
   1074       << GetStateDescription(state_)
   1075       << ", new = " << GetStateDescription(new_state);
   1076   first_time = false;
   1077 
   1078   // Pick action that should happen on leaving the old state.
   1079   switch (state_) {
   1080     case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY:
   1081     case PLAN_ACTIVATION_RECONNECTING:
   1082     case PLAN_ACTIVATION_RECONNECTING_OTASP:
   1083       if (reconnect_timer_.IsRunning()) {
   1084         reconnect_timer_.Stop();
   1085       }
   1086       break;
   1087     default:
   1088       break;
   1089   }
   1090   state_ = new_state;
   1091 
   1092   // Signal to JS layer that the state is changing.
   1093   UpdatePage(network, error_description);
   1094 
   1095   // Pick action that should happen on entering the new state.
   1096   switch (new_state) {
   1097     case PLAN_ACTIVATION_START:
   1098       break;
   1099     case PLAN_ACTIVATION_DELAY_OTASP: {
   1100       UMA_HISTOGRAM_COUNTS("Cellular.RetryOTASP", 1);
   1101       scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), 0);
   1102       BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
   1103           NewRunnableMethod(task.get(), &TaskProxy::RetryOTASP),
   1104           kOTASPRetryDelay);
   1105       break;
   1106     }
   1107     case PLAN_ACTIVATION_INITIATING_ACTIVATION:
   1108     case PLAN_ACTIVATION_TRYING_OTASP:
   1109     case PLAN_ACTIVATION_OTASP:
   1110       DCHECK(network);
   1111       LOG(WARNING) << "Activating service " << network->service_path().c_str();
   1112       UMA_HISTOGRAM_COUNTS("Cellular.ActivationTry", 1);
   1113       if (!network->StartActivation()) {
   1114         UMA_HISTOGRAM_COUNTS("Cellular.ActivationFailure", 1);
   1115         if (new_state == PLAN_ACTIVATION_OTASP) {
   1116           ChangeState(network, PLAN_ACTIVATION_DELAY_OTASP, std::string());
   1117         } else {
   1118           ChangeState(network, PLAN_ACTIVATION_ERROR,
   1119                       GetErrorMessage(kFailedConnectivity));
   1120         }
   1121       }
   1122       break;
   1123     case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY:
   1124     case PLAN_ACTIVATION_RECONNECTING:
   1125     case PLAN_ACTIVATION_RECONNECTING_OTASP: {
   1126       // Start reconnect timer. This will ensure that we are not left in
   1127       // limbo by the network library.
   1128       if (!reconnect_timer_.IsRunning()) {
   1129         reconnect_timer_.Start(
   1130             base::TimeDelta::FromMilliseconds(kReconnectTimerDelayMS),
   1131             this, &MobileSetupHandler::ReconnectTimerFired);
   1132       }
   1133       // Reset connection metrics and try to connect.
   1134       reconnect_wait_count_ = 0;
   1135       connection_retry_count_ = 0;
   1136       connection_start_time_ = base::Time::Now();
   1137       ConnectToNetwork(network, kReconnectDelayMS);
   1138       break;
   1139     }
   1140     case PLAN_ACTIVATION_PAGE_LOADING:
   1141       return;
   1142     case PLAN_ACTIVATION_SHOWING_PAYMENT:
   1143       // Fix for fix SSL for the walled gardens where cert chain verification
   1144       // might not work.
   1145       break;
   1146     case PLAN_ACTIVATION_DONE:
   1147       DCHECK(network);
   1148       CompleteActivation(network);
   1149       UMA_HISTOGRAM_COUNTS("Cellular.MobileSetupSucceeded", 1);
   1150       break;
   1151     case PLAN_ACTIVATION_ERROR:
   1152       CompleteActivation(NULL);
   1153       UMA_HISTOGRAM_COUNTS("Cellular.PlanFailed", 1);
   1154       break;
   1155     default:
   1156       break;
   1157   }
   1158 }
   1159 
   1160 void MobileSetupHandler::ReEnableOtherConnections() {
   1161   chromeos::NetworkLibrary* lib = chromeos::CrosLibrary::Get()->
   1162       GetNetworkLibrary();
   1163   if (reenable_ethernet_) {
   1164     reenable_ethernet_ = false;
   1165     lib->EnableEthernetNetworkDevice(true);
   1166   }
   1167   if (reenable_wifi_) {
   1168     reenable_wifi_ = false;
   1169     lib->EnableWifiNetworkDevice(true);
   1170   }
   1171 
   1172   PrefService* prefs = g_browser_process->local_state();
   1173   if (reenable_cert_check_) {
   1174     prefs->SetBoolean(prefs::kCertRevocationCheckingEnabled,
   1175                       true);
   1176     reenable_cert_check_ = false;
   1177   }
   1178 }
   1179 
   1180 void MobileSetupHandler::SetupActivationProcess(
   1181     chromeos::CellularNetwork* network) {
   1182   if (!network)
   1183     return;
   1184 
   1185   // Disable SSL cert checks since we will be doing this in
   1186   // restricted pool.
   1187   PrefService* prefs = g_browser_process->local_state();
   1188   if (!reenable_cert_check_ &&
   1189       prefs->GetBoolean(
   1190           prefs::kCertRevocationCheckingEnabled)) {
   1191     reenable_cert_check_ = true;
   1192     prefs->SetBoolean(prefs::kCertRevocationCheckingEnabled, false);
   1193   }
   1194 
   1195   chromeos::NetworkLibrary* lib = chromeos::CrosLibrary::Get()->
   1196       GetNetworkLibrary();
   1197   // Disable autoconnect to cellular network.
   1198   network->SetAutoConnect(false);
   1199 
   1200   // Prevent any other network interference.
   1201   DisableOtherNetworks();
   1202   lib->Lock();
   1203 }
   1204 
   1205 void MobileSetupHandler::DisableOtherNetworks() {
   1206   chromeos::NetworkLibrary* lib = chromeos::CrosLibrary::Get()->
   1207       GetNetworkLibrary();
   1208   // Disable ethernet and wifi.
   1209   if (lib->ethernet_enabled()) {
   1210     reenable_ethernet_ = true;
   1211     lib->EnableEthernetNetworkDevice(false);
   1212   }
   1213   if (lib->wifi_enabled()) {
   1214     reenable_wifi_ = true;
   1215     lib->EnableWifiNetworkDevice(false);
   1216   }
   1217 }
   1218 
   1219 bool MobileSetupHandler::GotActivationError(
   1220     chromeos::CellularNetwork* network, std::string* error) {
   1221   DCHECK(network);
   1222   bool got_error = false;
   1223   const char* error_code = kErrorDefault;
   1224 
   1225   // This is the magic for detection of errors in during activation process.
   1226   if (network->state() == chromeos::STATE_FAILURE &&
   1227       network->error() == chromeos::ERROR_AAA_FAILED) {
   1228     if (network->activation_state() ==
   1229             chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED) {
   1230       error_code = kErrorBadConnectionPartial;
   1231     } else if (network->activation_state() ==
   1232             chromeos::ACTIVATION_STATE_ACTIVATED) {
   1233       if (network->roaming_state() == chromeos::ROAMING_STATE_HOME) {
   1234         error_code = kErrorBadConnectionActivated;
   1235       } else if (network->roaming_state() == chromeos::ROAMING_STATE_ROAMING) {
   1236         error_code = kErrorRoamingOnConnection;
   1237       }
   1238     }
   1239     got_error = true;
   1240   } else if (network->state() == chromeos::STATE_ACTIVATION_FAILURE) {
   1241     if (network->error() == chromeos::ERROR_NEED_EVDO) {
   1242       if (network->activation_state() ==
   1243               chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED)
   1244         error_code = kErrorNoEVDO;
   1245     } else if (network->error() == chromeos::ERROR_NEED_HOME_NETWORK) {
   1246       if (network->activation_state() ==
   1247               chromeos::ACTIVATION_STATE_NOT_ACTIVATED) {
   1248         error_code = kErrorRoamingActivation;
   1249       } else if (network->activation_state() ==
   1250                     chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED) {
   1251         error_code = kErrorRoamingPartiallyActivated;
   1252       }
   1253     }
   1254     got_error = true;
   1255   }
   1256 
   1257   if (got_error)
   1258     *error = GetErrorMessage(error_code);
   1259 
   1260   return got_error;
   1261 }
   1262 
   1263 void MobileSetupHandler::GetDeviceInfo(chromeos::CellularNetwork* network,
   1264                                        DictionaryValue* value) {
   1265   DCHECK(network);
   1266   chromeos::NetworkLibrary* cros =
   1267       chromeos::CrosLibrary::Get()->GetNetworkLibrary();
   1268   if (!cros)
   1269     return;
   1270   value->SetString("carrier", network->name());
   1271   value->SetString("payment_url", network->payment_url());
   1272   const chromeos::NetworkDevice* device =
   1273       cros->FindNetworkDeviceByPath(network->device_path());
   1274   if (device) {
   1275     value->SetString("MEID", device->meid());
   1276     value->SetString("IMEI", device->imei());
   1277     value->SetString("MDN", device->mdn());
   1278   }
   1279 }
   1280 
   1281 std::string MobileSetupHandler::GetErrorMessage(const std::string& code) {
   1282   if (!cellular_config_.get())
   1283     return "";
   1284   return cellular_config_->GetErrorMessage(code);
   1285 }
   1286 
   1287 void MobileSetupHandler::LoadCellularConfig() {
   1288   static bool config_loaded = false;
   1289   if (config_loaded)
   1290     return;
   1291   config_loaded = true;
   1292   // Load partner customization startup manifest if it is available.
   1293   FilePath config_path(kCellularConfigPath);
   1294   bool config_exists = false;
   1295   {
   1296     // Reading config file causes us to do blocking IO on UI thread.
   1297     // Temporarily allow it until we fix http://crosbug.com/11535
   1298     base::ThreadRestrictions::ScopedAllowIO allow_io;
   1299     config_exists = file_util::PathExists(config_path);
   1300   }
   1301   if (config_exists) {
   1302     scoped_ptr<CellularConfigDocument> config(new CellularConfigDocument());
   1303     bool config_loaded = config->LoadFromFile(config_path);
   1304     if (config_loaded) {
   1305       LOG(INFO) << "Cellular config file loaded: " << kCellularConfigPath;
   1306       // lock
   1307       cellular_config_.reset(config.release());
   1308     } else {
   1309       LOG(ERROR) << "Error loading cellular config file: " <<
   1310           kCellularConfigPath;
   1311     }
   1312   }
   1313 }
   1314 
   1315 
   1316 ////////////////////////////////////////////////////////////////////////////////
   1317 //
   1318 // MobileSetupUI
   1319 //
   1320 ////////////////////////////////////////////////////////////////////////////////
   1321 
   1322 MobileSetupUI::MobileSetupUI(TabContents* contents) : WebUI(contents) {
   1323   chromeos::CellularNetwork* network = GetCellularNetwork();
   1324   std::string service_path = network ? network->service_path() : std::string();
   1325   MobileSetupHandler* handler = new MobileSetupHandler(service_path);
   1326   AddMessageHandler((handler)->Attach(this));
   1327   handler->Init(contents);
   1328   MobileSetupUIHTMLSource* html_source =
   1329       new MobileSetupUIHTMLSource(service_path);
   1330 
   1331   // Set up the chrome://mobilesetup/ source.
   1332   contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
   1333 }
   1334