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