Chromium Code Reviews| Index: chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc |
| =================================================================== |
| --- chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc (revision 71286) |
| +++ chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc (working copy) |
| @@ -19,6 +19,7 @@ |
| #include "base/string_piece.h" |
| #include "base/string_util.h" |
| #include "base/utf_string_conversions.h" |
| +#include "base/timer.h" |
| #include "base/values.h" |
| #include "base/weak_ptr.h" |
| #include "chrome/browser/browser_list.h" |
| @@ -73,9 +74,23 @@ |
| // there is no connectivity in the restricted pool. |
| const int kMaxActivationAttempt = 3; |
| // Number of times we will retry to reconnect if connection fails. |
| -const int kMaxConnectionRetry = 3; |
| +const int kMaxConnectionRetry = 10; |
| +// Number of times we will retry to reconnect if connection fails. |
| +const int kMaxConnectionRetryOTASP = 30; |
| +// Number of times we will retry to reconnect after payment is processed. |
| +const int kMaxReconnectAttemptOTASP = 30; |
| +// Reconnect retry delay (after payment is processed). |
| +const int kPostPaymentReconnectDelayMS = 30000; // 30s. |
| // Connection timeout in seconds. |
| -const int kConnectionTimeoutSeconds = 30; |
| +const int kConnectionTimeoutSeconds = 45; |
| +// Reconnect delay. |
| +const int kReconnectDelayMS = 3000; |
| +// Reconnect timer delay. |
| +const int kReconnectTimerDelayMS = 1000; |
| +// Reconnect delay after previous failure. |
| +const int kFailedReconnectDelayMS = 10000; |
| +// Retry delay after failed OTASP attempt. |
| +const int kOTASPRetryDelay = 10000; |
| chromeos::CellularNetwork* GetCellularNetwork() { |
| chromeos::NetworkLibrary* lib = chromeos::CrosLibrary::Get()-> |
| @@ -157,19 +172,25 @@ |
| private: |
| typedef enum PlanActivationState { |
| - PLAN_ACTIVATION_PAGE_LOADING = -1, |
| - PLAN_ACTIVATION_START = 0, |
| - PLAN_ACTIVATION_INITIATING_ACTIVATION = 1, |
| - PLAN_ACTIVATION_RECONNECTING = 2, |
| - PLAN_ACTIVATION_SHOWING_PAYMENT = 3, |
| - PLAN_ACTIVATION_DONE = 4, |
| - PLAN_ACTIVATION_ERROR = 5, |
| + PLAN_ACTIVATION_PAGE_LOADING = -1, |
| + PLAN_ACTIVATION_START = 0, |
| + PLAN_ACTIVATION_TRYING_OTASP = 1, |
| + PLAN_ACTIVATION_RECONNECTING_OTASP_TRY = 2, |
| + PLAN_ACTIVATION_INITIATING_ACTIVATION = 3, |
| + PLAN_ACTIVATION_RECONNECTING = 4, |
| + PLAN_ACTIVATION_SHOWING_PAYMENT = 5, |
| + PLAN_ACTIVATION_DELAY_OTASP = 6, |
| + PLAN_ACTIVATION_START_OTASP = 7, |
| + PLAN_ACTIVATION_OTASP = 8, |
| + PLAN_ACTIVATION_RECONNECTING_OTASP = 9, |
| + PLAN_ACTIVATION_DONE = 10, |
| + PLAN_ACTIVATION_ERROR = 0xFF, |
| } PlanActivationState; |
| class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> { |
| public: |
| - explicit TaskProxy(const base::WeakPtr<MobileSetupHandler>& handler) |
| - : handler_(handler) { |
| + TaskProxy(const base::WeakPtr<MobileSetupHandler>& handler, int delay) |
| + : handler_(handler), delay_(delay) { |
| } |
| TaskProxy(const base::WeakPtr<MobileSetupHandler>& handler, |
| const std::string& status) |
| @@ -183,13 +204,18 @@ |
| if (handler_) |
| handler_->SetTransactionStatus(status_); |
| } |
| - void ContinueActivation() { |
| + void ContinueConnecting() { |
| if (handler_) |
| - handler_->ContinueActivation(); |
| + handler_->ContinueConnecting(delay_); |
| } |
| + void RetryOTASP() { |
| + if (handler_) |
| + handler_->RetryOTASP(); |
| + } |
| private: |
| base::WeakPtr<MobileSetupHandler> handler_; |
| std::string status_; |
| + int delay_; |
| DISALLOW_COPY_AND_ASSIGN(TaskProxy); |
| }; |
| @@ -201,17 +227,29 @@ |
| void InitiateActivation(); |
| // Starts activation. |
| void StartActivation(); |
| + // Retried OTASP. |
| + void RetryOTASP(); |
| // Continues activation process. This method is called after we disconnect |
| // due to detected connectivity issue to kick off reconnection. |
| - void ContinueActivation(); |
| + void ContinueConnecting(int delay); |
| // Sends message to host registration page with system/user info data. |
| void SendDeviceInfo(); |
| + // Callback for when |reconnect_timer_| fires. |
| + void ReconnectTimerFired(); |
| + // Starts OTASP process. |
| + void StartOTASP(); |
| + // Checks if we need to reconnect due to failed connection attempt. |
| + bool NeedsReconnecting(chromeos::CellularNetwork* network, |
| + PlanActivationState* new_state, |
| + std::string* error_description); |
| + // Disconnect from network. |
| + void DisconnectFromNetwork(chromeos::CellularNetwork* network); |
| // Connects to cellular network, resets connection timer. |
| - void ConnectToNetwork(chromeos::CellularNetwork* network); |
| + bool ConnectToNetwork(chromeos::CellularNetwork* network, int delay); |
| // Forces disconnect / reconnect when we detect portal connectivity issues. |
| - void ForceReconnect(chromeos::CellularNetwork* network); |
| + void ForceReconnect(chromeos::CellularNetwork* network, int delay); |
| // Reports connection timeout. |
| bool ConnectionTimeout(); |
| // Verify the state of cellular network and modify internal state. |
| @@ -254,6 +292,8 @@ |
| static std::string GetErrorMessage(const std::string& code); |
| static void LoadCellularConfig(); |
| + // Returns next reconnection state based on the current activation phase. |
| + static PlanActivationState GetNextReconnectState(PlanActivationState state); |
| static const char* GetStateDescription(PlanActivationState state); |
| static scoped_ptr<CellularConfigDocument> cellular_config_; |
| @@ -267,15 +307,18 @@ |
| bool reenable_wifi_; |
| bool reenable_ethernet_; |
| bool reenable_cert_check_; |
| - bool transaction_complete_signalled_; |
| - bool activation_status_test_; |
| bool evaluating_; |
| // Connection retry counter. |
| int connection_retry_count_; |
| + // Post payment reconnect wait counters. |
| + int reconnect_wait_count_; |
| // Activation retry attempt count; |
| int activation_attempt_; |
| // Connection start time. |
| base::Time connection_start_time_; |
| + // Timer that monitors reconnection timeouts. |
| + base::RepeatingTimer<MobileSetupHandler> reconnect_timer_; |
| + |
| DISALLOW_COPY_AND_ASSIGN(MobileSetupHandler); |
| }; |
| @@ -370,9 +413,10 @@ |
| static const base::StringPiece html( |
| ResourceBundle::GetSharedInstance().GetRawDataResource( |
| IDR_MOBILE_SETUP_PAGE_HTML)); |
| - const std::string full_html = jstemplate_builder::GetTemplatesHtml( |
| - html, &strings, "t" /* template root node id */); |
| + const std::string full_html = jstemplate_builder::GetI18nTemplateHtml( |
| + html, &strings); |
| + |
| scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); |
| html_bytes->data.resize(full_html.size()); |
| std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin()); |
| @@ -392,14 +436,14 @@ |
| reenable_wifi_(false), |
| reenable_ethernet_(false), |
| reenable_cert_check_(false), |
| - transaction_complete_signalled_(false), |
| - activation_status_test_(false), |
| evaluating_(false), |
| connection_retry_count_(0), |
| + reconnect_wait_count_(0), |
| activation_attempt_(0) { |
| } |
| MobileSetupHandler::~MobileSetupHandler() { |
| + reconnect_timer_.Stop(); |
| chromeos::NetworkLibrary* lib = |
| chromeos::CrosLibrary::Get()->GetNetworkLibrary(); |
| lib->RemoveNetworkManagerObserver(this); |
| @@ -464,7 +508,7 @@ |
| } |
| void MobileSetupHandler::InitiateActivation() { |
| - scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr()); |
| + scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), 0); |
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| NewRunnableMethod(task.get(), &TaskProxy::HandleStartActivation)); |
| } |
| @@ -482,14 +526,27 @@ |
| lib->AddNetworkManagerObserver(this); |
| lib->RemoveObserverForAllNetworks(this); |
| lib->AddNetworkObserver(network->service_path(), this); |
| - state_ = PLAN_ACTIVATION_START; |
| + // Try to start with OTASP immediately if we have received payment recently. |
| + state_ = lib->HasRecentCellularPlanPayment() ? |
| + PLAN_ACTIVATION_START_OTASP : |
| + PLAN_ACTIVATION_START; |
| EvaluateCellularNetwork(network); |
| } |
| -void MobileSetupHandler::ContinueActivation() { |
| +void MobileSetupHandler::RetryOTASP() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + DCHECK(state_ == PLAN_ACTIVATION_DELAY_OTASP); |
| + StartOTASP(); |
| +} |
| + |
| +void MobileSetupHandler::ContinueConnecting(int delay) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| chromeos::CellularNetwork* network = GetCellularNetwork(service_path_); |
| - EvaluateCellularNetwork(network); |
| + if (network && network->connecting_or_connected()) { |
| + EvaluateCellularNetwork(network); |
| + } else { |
| + ConnectToNetwork(network, delay); |
| + } |
| } |
| void MobileSetupHandler::SetTransactionStatus(const std::string& status) { |
| @@ -498,42 +555,108 @@ |
| // again. |
| if (LowerCaseEqualsASCII(status, "ok") && |
| state_ == PLAN_ACTIVATION_SHOWING_PAYMENT) { |
| + chromeos::NetworkLibrary* lib = |
| + chromeos::CrosLibrary::Get()->GetNetworkLibrary(); |
| + lib->SignalCellularPlanPayment(); |
| UMA_HISTOGRAM_COUNTS("Cellular.PaymentReceived", 1); |
| - if (transaction_complete_signalled_) { |
| - LOG(WARNING) << "Transaction completion signaled more than once!?"; |
| - return; |
| - } |
| - transaction_complete_signalled_ = true; |
| - activation_status_test_ = false; |
| - state_ = PLAN_ACTIVATION_START; |
| - chromeos::CellularNetwork* network = GetCellularNetwork(); |
| - if (network && |
| - network->activation_state() == chromeos::ACTIVATION_STATE_ACTIVATED) { |
| - chromeos::CrosLibrary::Get()->GetNetworkLibrary()-> |
| - DisconnectFromWirelessNetwork(network); |
| - } else { |
| - EvaluateCellularNetwork(network); |
| - } |
| + StartOTASP(); |
| } else { |
| UMA_HISTOGRAM_COUNTS("Cellular.PaymentFailed", 1); |
| } |
| } |
| +void MobileSetupHandler::StartOTASP() { |
| + state_ = PLAN_ACTIVATION_START_OTASP; |
| + chromeos::CellularNetwork* network = GetCellularNetwork(); |
| + if (network && |
| + network->connected() && |
| + network->activation_state() == chromeos::ACTIVATION_STATE_ACTIVATED) { |
| + chromeos::CrosLibrary::Get()->GetNetworkLibrary()-> |
| + DisconnectFromWirelessNetwork(network); |
| + } else { |
| + EvaluateCellularNetwork(network); |
| + } |
| +} |
| -void MobileSetupHandler::ConnectToNetwork(chromeos::CellularNetwork* network) { |
| - DCHECK(network); |
| - LOG(INFO) << "Connecting to " << |
| +void MobileSetupHandler::ReconnectTimerFired() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + if (state_ != PLAN_ACTIVATION_RECONNECTING_OTASP_TRY && |
| + state_ != PLAN_ACTIVATION_RECONNECTING && |
| + state_ != PLAN_ACTIVATION_RECONNECTING_OTASP) |
| + return; |
| + chromeos::CellularNetwork* network = GetCellularNetwork(service_path_); |
| + if (!network) { |
| + ChangeState(NULL, PLAN_ACTIVATION_ERROR, std::string()); |
| + return; |
| + } |
| + EvaluateCellularNetwork(network); |
| +} |
| + |
| +void MobileSetupHandler::DisconnectFromNetwork( |
| + chromeos::CellularNetwork* network) { |
| + LOG(INFO) << "Disconnecting from " << |
| network->service_path().c_str(); |
| + chromeos::CrosLibrary::Get()->GetNetworkLibrary()-> |
| + DisconnectFromWirelessNetwork(network); |
| + // Disconnect will force networks to be reevaluated, so |
| + // we don't want to continue processing on this path anymore. |
| + evaluating_ = false; |
| +} |
| + |
| +bool MobileSetupHandler::NeedsReconnecting(chromeos::CellularNetwork* network, |
| + PlanActivationState* new_state, |
| + std::string* error_description) { |
| + if (!network->failed() && !ConnectionTimeout()) |
| + return false; |
| + |
| + // Try to reconnect again if reconnect failed, or if for some |
| + // reasons we are still not connected after 45 seconds. |
| + int max_retries = (state_ == PLAN_ACTIVATION_RECONNECTING_OTASP) ? |
| + kMaxConnectionRetryOTASP : kMaxConnectionRetry; |
| + if (connection_retry_count_ < max_retries) { |
| + UMA_HISTOGRAM_COUNTS("Cellular.ConnectionRetry", 1); |
| + ConnectToNetwork(network, kFailedReconnectDelayMS); |
| + return true; |
| + } |
| + // We simply can't connect anymore after all these tries. |
| + UMA_HISTOGRAM_COUNTS("Cellular.ConnectionFailed", 1); |
| + *new_state = PLAN_ACTIVATION_ERROR; |
| + *error_description = GetErrorMessage(kFailedConnectivity); |
| + return false; |
| +} |
| + |
| +bool MobileSetupHandler::ConnectToNetwork(chromeos::CellularNetwork* network, |
| + int delay) { |
| + if (network && network->connecting_or_connected()) |
| + return true; |
| + if (state_ != PLAN_ACTIVATION_RECONNECTING_OTASP_TRY && |
| + state_ != PLAN_ACTIVATION_RECONNECTING && |
| + state_ != PLAN_ACTIVATION_RECONNECTING_OTASP) |
| + return false; |
| + if (network) { |
| + LOG(INFO) << "Connecting to " << |
| + network->service_path().c_str(); |
| + } |
| connection_retry_count_++; |
| connection_start_time_ = base::Time::Now(); |
| - if (!chromeos::CrosLibrary::Get()->GetNetworkLibrary()-> |
| + if (!network || !chromeos::CrosLibrary::Get()->GetNetworkLibrary()-> |
| ConnectToCellularNetwork(network)) { |
| LOG(WARNING) << "Connect failed for service " |
| << network->service_path().c_str(); |
|
Jason Glasgow
2011/01/14 07:58:42
network can be NULL, so it is not okay to log netw
zel
2011/01/14 17:35:02
Done.
|
| + // If we coudn't connect during reconnection phase, try to reconnect |
| + // with a delay (and try to reconnect if needed). |
| + scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), |
| + delay); |
| + BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, |
| + NewRunnableMethod(task.get(), &TaskProxy::ContinueConnecting), |
| + delay); |
| + return false; |
| } |
| + return true; |
| } |
| -void MobileSetupHandler::ForceReconnect(chromeos::CellularNetwork* network) { |
| +void MobileSetupHandler::ForceReconnect(chromeos::CellularNetwork* network, |
| + int delay) { |
| DCHECK(network); |
| UMA_HISTOGRAM_COUNTS("Cellular.ActivationRetry", 1); |
| // Reset reconnect metrics. |
| @@ -546,11 +669,10 @@ |
| DisconnectFromWirelessNetwork(network); |
| // Check the network state 3s after we disconnect to make sure. |
| scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), |
| - std::string()); |
| - const int kReconnectDelayMS = 3000; |
| + delay); |
| BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, |
| - NewRunnableMethod(task.get(), &TaskProxy::ContinueActivation), |
| - kReconnectDelayMS); |
| + NewRunnableMethod(task.get(), &TaskProxy::ContinueConnecting), |
| + delay); |
| } |
| bool MobileSetupHandler::ConnectionTimeout() { |
| @@ -566,7 +688,9 @@ |
| PlanActivationState new_state = state_; |
| if (!network) { |
| LOG(WARNING) << "Cellular service lost"; |
| - if (state_ == PLAN_ACTIVATION_RECONNECTING) { |
| + if (state_ == PLAN_ACTIVATION_RECONNECTING_OTASP_TRY || |
| + state_ == PLAN_ACTIVATION_RECONNECTING || |
| + state_ == PLAN_ACTIVATION_RECONNECTING_OTASP) { |
| // This might be the legit case when service is lost after activation. |
| // We need to make sure we force reconnection as soon as it shows up. |
| LOG(INFO) << "Force service reconnection"; |
| @@ -582,13 +706,13 @@ |
| evaluating_ = true; |
| std::string error_description; |
| - LOG(INFO) << "Cellular:\n service=" << network->GetStateString().c_str() |
| - << "\n ui=" << GetStateDescription(state_) |
| - << "\n activation=" << network->GetActivationStateString().c_str() |
| - << "\n connectivity=" |
| - << network->GetConnectivityStateString().c_str() |
| - << "\n error=" << network->GetErrorString().c_str() |
| - << "\n setvice_path=" << network->service_path().c_str(); |
| + LOG(WARNING) << "Cellular:\n service=" << network->GetStateString().c_str() |
| + << "\n ui=" << GetStateDescription(state_) |
| + << "\n activation=" << network->GetActivationStateString().c_str() |
| + << "\n connectivity=" |
| + << network->GetConnectivityStateString().c_str() |
| + << "\n error=" << network->GetErrorString().c_str() |
| + << "\n setvice_path=" << network->service_path().c_str(); |
| switch (state_) { |
| case PLAN_ACTIVATION_START: { |
| switch (network->activation_state()) { |
| @@ -604,58 +728,54 @@ |
| } |
| break; |
| } |
| - case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED: { |
| - if (!activation_status_test_) { |
| - if (network->failed_or_disconnected()) { |
| - activation_status_test_ = true; |
| - new_state = PLAN_ACTIVATION_INITIATING_ACTIVATION; |
| - } else if (network->connected()) { |
| - LOG(INFO) << "Disconnecting from " << |
| - network->service_path().c_str(); |
| - chromeos::CrosLibrary::Get()->GetNetworkLibrary()-> |
| - DisconnectFromWirelessNetwork(network); |
| - // Disconnect will force networks to be reevaluated, so |
| - // we don't want to continue processing on this path anymore. |
| - evaluating_ = false; |
| - return; |
| - } |
| - } else { |
| - if (network->connected()) { |
| - if (network->restricted_pool()) |
| - new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; |
| - } else { |
| - new_state = PLAN_ACTIVATION_RECONNECTING; |
| - } |
| - break; |
| + default: { |
| + if (network->failed_or_disconnected()) { |
| + new_state = (network->activation_state() == |
| + chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED) ? |
| + PLAN_ACTIVATION_TRYING_OTASP : |
| + PLAN_ACTIVATION_INITIATING_ACTIVATION; |
| + } else if (network->connected()) { |
| + DisconnectFromNetwork(network); |
| + return; |
| } |
| break; |
| } |
| - case chromeos::ACTIVATION_STATE_UNKNOWN: |
| - case chromeos::ACTIVATION_STATE_NOT_ACTIVATED: { |
| + } |
| + break; |
| + } |
| + case PLAN_ACTIVATION_START_OTASP: { |
| + switch (network->activation_state()) { |
| + case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED: { |
| if (network->failed_or_disconnected()) { |
| - new_state = PLAN_ACTIVATION_INITIATING_ACTIVATION; |
| + new_state = PLAN_ACTIVATION_OTASP; |
| } else if (network->connected()) { |
| - LOG(INFO) << "Disconnecting from " << |
| - network->service_path().c_str(); |
| - chromeos::CrosLibrary::Get()->GetNetworkLibrary()-> |
| - DisconnectFromWirelessNetwork(network); |
| - // Disconnect will force networks to be reevaluated, so |
| - // we don't want to continue processing on this path anymore. |
| - evaluating_ = false; |
| + DisconnectFromNetwork(network); |
| return; |
| } |
| break; |
| } |
| - default: |
| + case chromeos::ACTIVATION_STATE_ACTIVATED: |
| + new_state = PLAN_ACTIVATION_RECONNECTING_OTASP; |
| break; |
| + default: { |
| + LOG(WARNING) << "Unexpected activation state for device " |
| + << network->service_path().c_str(); |
| + break; |
| + } |
| } |
| break; |
| } |
| - case PLAN_ACTIVATION_INITIATING_ACTIVATION: { |
| + case PLAN_ACTIVATION_DELAY_OTASP: |
| + // Just ignore any changes until the OTASP retry timer kicks in. |
| + evaluating_ = false; |
| + return; |
| + case PLAN_ACTIVATION_INITIATING_ACTIVATION: |
| + case PLAN_ACTIVATION_OTASP: |
| + case PLAN_ACTIVATION_TRYING_OTASP: { |
| switch (network->activation_state()) { |
| case chromeos::ACTIVATION_STATE_ACTIVATED: |
| if (network->failed_or_disconnected()) { |
| - new_state = PLAN_ACTIVATION_RECONNECTING; |
| + new_state = GetNextReconnectState(state_); |
| } else if (network->connected()) { |
| if (network->restricted_pool()) { |
| new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; |
| @@ -669,20 +789,20 @@ |
| if (network->restricted_pool()) |
| new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; |
| } else { |
| - new_state = PLAN_ACTIVATION_RECONNECTING; |
| + new_state = GetNextReconnectState(state_); |
| } |
| break; |
| case chromeos::ACTIVATION_STATE_NOT_ACTIVATED: |
| + case chromeos::ACTIVATION_STATE_ACTIVATING: |
| // Wait in this state until activation state changes. |
| break; |
| - case chromeos::ACTIVATION_STATE_ACTIVATING: |
| - break; |
| default: |
| break; |
| } |
| break; |
| } |
| - case PLAN_ACTIVATION_RECONNECTING: { |
| + case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY: |
| + case PLAN_ACTIVATION_RECONNECTING: { |
| if (network->connected()) { |
| // Make sure other networks are not interfering with our detection of |
| // restricted pool. |
| @@ -697,18 +817,20 @@ |
| << network->service_path().c_str(); |
| // If we are connected but there is no connectivity at all, |
| // restart the whole process again. |
| - new_state = PLAN_ACTIVATION_ERROR; |
| if (activation_attempt_ < kMaxActivationAttempt) { |
| activation_attempt_++; |
| - ForceReconnect(network); |
| + ForceReconnect(network, kFailedReconnectDelayMS); |
| evaluating_ = false; |
| return; |
| } else { |
| + new_state = PLAN_ACTIVATION_ERROR; |
| UMA_HISTOGRAM_COUNTS("Cellular.ActivationRetryFailure", 1); |
| error_description = GetErrorMessage(kFailedConnectivity); |
| } |
| } else if (network->connectivity_state() == |
| - chromeos::CONN_STATE_RESTRICTED) { |
| + chromeos::CONN_STATE_RESTRICTED) { |
| + // If we have already received payment, don't show the payment |
| + // page again. We should try to reconnect after some time instead. |
| new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; |
| } else if (network->activation_state() == |
| chromeos::ACTIVATION_STATE_ACTIVATED) { |
| @@ -718,20 +840,49 @@ |
| default: |
| break; |
| } |
| - } else if (network->failed() || ConnectionTimeout()) { |
| - // Try to reconnect again if reconnect failed, or if for some |
| - // reasons we are still not connected after 30 seconds. |
| - if (connection_retry_count_ < kMaxConnectionRetry) { |
| - UMA_HISTOGRAM_COUNTS("Cellular.ConnectionRetry", 1); |
| - ConnectToNetwork(network); |
| - evaluating_ = false; |
| - return; |
| - } else { |
| - // We simply can't connect anymore after all these tries. |
| - UMA_HISTOGRAM_COUNTS("Cellular.ConnectionFailed", 1); |
| - new_state = PLAN_ACTIVATION_ERROR; |
| - error_description = GetErrorMessage(kFailedConnectivity); |
| + } else if (NeedsReconnecting(network, &new_state, &error_description)) { |
| + evaluating_ = false; |
| + return; |
| + } |
| + break; |
| + } |
| + case PLAN_ACTIVATION_RECONNECTING_OTASP: { |
| + if (network->connected()) { |
| + // Make sure other networks are not interfering with our detection of |
| + // restricted pool. |
| + DisableOtherNetworks(); |
| + // Wait until the service shows up and gets activated. |
| + switch (network->activation_state()) { |
| + case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED: |
| + case chromeos::ACTIVATION_STATE_ACTIVATED: |
| + if (network->connectivity_state() == chromeos::CONN_STATE_NONE || |
| + network->connectivity_state() == |
| + chromeos::CONN_STATE_RESTRICTED) { |
| + LOG(WARNING) << "Still no connectivity after OTASP for device " |
| + << network->service_path().c_str(); |
| + // If we have already received payment, don't show the payment |
| + // page again. We should try to reconnect after some time instead. |
| + if (reconnect_wait_count_ < kMaxReconnectAttemptOTASP) { |
| + reconnect_wait_count_++; |
| + ForceReconnect(network, kPostPaymentReconnectDelayMS); |
| + evaluating_ = false; |
| + return; |
| + } else { |
| + new_state = PLAN_ACTIVATION_ERROR; |
| + UMA_HISTOGRAM_COUNTS("Cellular.PostPaymentConnectFailure", 1); |
| + error_description = GetErrorMessage(kFailedConnectivity); |
| + } |
| + } else if (network->connectivity_state() == |
| + chromeos::CONN_STATE_UNRESTRICTED) { |
| + new_state = PLAN_ACTIVATION_DONE; |
| + } |
| + break; |
| + default: |
| + break; |
| } |
| + } else if (NeedsReconnecting(network, &new_state, &error_description)) { |
| + evaluating_ = false; |
| + return; |
| } |
| break; |
| } |
| @@ -754,20 +905,57 @@ |
| chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED || |
| network->activation_state() == chromeos::ACTIVATION_STATE_ACTIVATING) && |
| (network->error() == chromeos::ERROR_UNKNOWN || |
| - network->error() == chromeos::ERROR_OTASP_FAILED)&& |
| - (state_ == PLAN_ACTIVATION_INITIATING_ACTIVATION || |
| - state_ == PLAN_ACTIVATION_RECONNECTING) && |
| - activation_status_test_ && |
| + network->error() == chromeos::ERROR_OTASP_FAILED) && |
| network->connection_state() == chromeos::STATE_ACTIVATION_FAILURE) { |
| - new_state = PLAN_ACTIVATION_RECONNECTING; |
| + LOG(WARNING) << "Activation failure detected " |
| + << network->service_path().c_str(); |
| + switch (state_) { |
| + case PLAN_ACTIVATION_OTASP: |
| + case PLAN_ACTIVATION_RECONNECTING_OTASP: |
| + new_state = PLAN_ACTIVATION_DELAY_OTASP; |
| + break; |
| + case PLAN_ACTIVATION_TRYING_OTASP: |
| + new_state = PLAN_ACTIVATION_RECONNECTING_OTASP_TRY; |
| + break; |
| + case PLAN_ACTIVATION_INITIATING_ACTIVATION: |
| + new_state = PLAN_ACTIVATION_RECONNECTING; |
| + break; |
| + case PLAN_ACTIVATION_DELAY_OTASP: |
| + case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY: |
| + case PLAN_ACTIVATION_RECONNECTING: |
| + new_state = state_; |
| + break; |
| + default: |
| + new_state = PLAN_ACTIVATION_ERROR; |
| + break; |
| + } |
| } else { |
| new_state = PLAN_ACTIVATION_ERROR; |
| } |
| } |
| + |
| + if (new_state == PLAN_ACTIVATION_ERROR && !error_description.length()) |
| + error_description = GetErrorMessage(kFailedConnectivity); |
| + |
| ChangeState(network, new_state, error_description); |
| evaluating_ = false; |
| } |
| +MobileSetupHandler::PlanActivationState |
| + MobileSetupHandler::GetNextReconnectState( |
| + MobileSetupHandler::PlanActivationState state) { |
| + switch (state) { |
| + case PLAN_ACTIVATION_INITIATING_ACTIVATION: |
| + return PLAN_ACTIVATION_RECONNECTING; |
| + case PLAN_ACTIVATION_OTASP: |
| + return PLAN_ACTIVATION_RECONNECTING_OTASP; |
| + case PLAN_ACTIVATION_TRYING_OTASP: |
| + return PLAN_ACTIVATION_RECONNECTING_OTASP_TRY; |
| + default: |
| + return PLAN_ACTIVATION_RECONNECTING; |
| + } |
| +} |
| + |
| // Debugging helper function, will take it out at the end. |
| const char* MobileSetupHandler::GetStateDescription( |
| PlanActivationState state) { |
| @@ -776,12 +964,24 @@ |
| return "PAGE_LOADING"; |
| case PLAN_ACTIVATION_START: |
| return "ACTIVATION_START"; |
| + case PLAN_ACTIVATION_TRYING_OTASP: |
| + return "TRYING_OTASP"; |
| + case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY: |
| + return "RECONNECTING_OTASP_TRY"; |
| case PLAN_ACTIVATION_INITIATING_ACTIVATION: |
| return "INITIATING_ACTIVATION"; |
| case PLAN_ACTIVATION_RECONNECTING: |
| return "RECONNECTING"; |
| case PLAN_ACTIVATION_SHOWING_PAYMENT: |
| return "SHOWING_PAYMENT"; |
| + case PLAN_ACTIVATION_START_OTASP: |
| + return "START_OTASP"; |
| + case PLAN_ACTIVATION_DELAY_OTASP: |
| + return "DELAY_OTASP"; |
| + case PLAN_ACTIVATION_OTASP: |
| + return "OTASP"; |
| + case PLAN_ACTIVATION_RECONNECTING_OTASP: |
| + return "RECONNECTING_OTASP"; |
| case PLAN_ACTIVATION_DONE: |
| return "DONE"; |
| case PLAN_ACTIVATION_ERROR: |
| @@ -820,39 +1020,73 @@ |
| kJsDeviceStatusChangedHandler, device_dict); |
| } |
| + |
| void MobileSetupHandler::ChangeState(chromeos::CellularNetwork* network, |
| PlanActivationState new_state, |
| const std::string& error_description) { |
| static bool first_time = true; |
| if (state_ == new_state && !first_time) |
| return; |
| - LOG(INFO) << "Activation state flip old = " << |
| - GetStateDescription(state_) << ", new = " << |
| - GetStateDescription(new_state); |
| + LOG(WARNING) << "Activation state flip old = " |
| + << GetStateDescription(state_) |
| + << ", new = " << GetStateDescription(new_state); |
| first_time = false; |
| + |
| + // Pick action that should happen on leaving the old state. |
| + switch (state_) { |
| + case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY: |
| + case PLAN_ACTIVATION_RECONNECTING: |
| + case PLAN_ACTIVATION_RECONNECTING_OTASP: |
| + if (reconnect_timer_.IsRunning()) { |
| + reconnect_timer_.Stop(); |
| + } |
| + break; |
| + default: |
| + break; |
| + } |
| state_ = new_state; |
| // Signal to JS layer that the state is changing. |
| UpdatePage(network, error_description); |
| - // Decide what to do with network object as a result of the new state. |
| + // 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); |
| + scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), 0); |
| + BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, |
| + NewRunnableMethod(task.get(), &TaskProxy::RetryOTASP), |
| + kOTASPRetryDelay); |
| + break; |
| + } |
| case PLAN_ACTIVATION_INITIATING_ACTIVATION: |
| + case PLAN_ACTIVATION_TRYING_OTASP: |
| + case PLAN_ACTIVATION_OTASP: |
| DCHECK(network); |
| - LOG(INFO) << "Activating service " << network->service_path().c_str(); |
| + LOG(WARNING) << "Activating service " << network->service_path().c_str(); |
| UMA_HISTOGRAM_COUNTS("Cellular.ActivationTry", 1); |
| if (!network->StartActivation()) { |
| UMA_HISTOGRAM_COUNTS("Cellular.ActivationFailure", 1); |
| ChangeState(network, PLAN_ACTIVATION_ERROR, std::string()); |
| } |
| break; |
| - case PLAN_ACTIVATION_RECONNECTING: { |
| + case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY: |
| + case PLAN_ACTIVATION_RECONNECTING: |
| + case PLAN_ACTIVATION_RECONNECTING_OTASP: { |
| + // Start reconnect timer. This will ensure that we are not left in |
| + // limbo by the network library. |
| + if (!reconnect_timer_.IsRunning()) { |
| + reconnect_timer_.Start( |
| + base::TimeDelta::FromMilliseconds(kReconnectTimerDelayMS), |
| + this, &MobileSetupHandler::ReconnectTimerFired); |
| + } |
| // Reset connection metrics and try to connect. |
| + reconnect_wait_count_ = 0; |
| connection_retry_count_ = 0; |
| connection_start_time_ = base::Time::Now(); |
| - ConnectToNetwork(network); |
| + ConnectToNetwork(network, kReconnectDelayMS); |
| break; |
| } |
| case PLAN_ACTIVATION_PAGE_LOADING: |
| @@ -866,11 +1100,10 @@ |
| CompleteActivation(network); |
| UMA_HISTOGRAM_COUNTS("Cellular.MobileSetupSucceeded", 1); |
| break; |
| - case PLAN_ACTIVATION_ERROR: { |
| + case PLAN_ACTIVATION_ERROR: |
| CompleteActivation(NULL); |
| UMA_HISTOGRAM_COUNTS("Cellular.PlanFailed", 1); |
| break; |
| - } |
| default: |
| break; |
| } |