Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1231)

Side by Side Diff: chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc

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

Powered by Google App Engine
This is Rietveld 408576698