NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / ui / webui / chromeos / sim_unlock_ui.cc
blob06a809cf4404f39f8b2f21924b13055854b2477a
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
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/webui/chromeos/sim_unlock_ui.h"
7 #include <string>
9 #include "base/basictypes.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted_memory.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/strings/string_piece.h"
18 #include "base/values.h"
19 #include "chrome/browser/chrome_notification_types.h"
20 #include "chrome/browser/chromeos/sim_dialog_delegate.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/common/url_constants.h"
23 #include "chromeos/network/device_state.h"
24 #include "chromeos/network/network_device_handler.h"
25 #include "chromeos/network/network_event_log.h"
26 #include "chromeos/network/network_state_handler.h"
27 #include "chromeos/network/network_state_handler_observer.h"
28 #include "chromeos/network/shill_property_util.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/url_data_source.h"
32 #include "content/public/browser/web_contents.h"
33 #include "content/public/browser/web_ui.h"
34 #include "content/public/browser/web_ui_message_handler.h"
35 #include "grit/browser_resources.h"
36 #include "grit/generated_resources.h"
37 #include "third_party/cros_system_api/dbus/service_constants.h"
38 #include "ui/base/l10n/l10n_util.h"
39 #include "ui/base/resource/resource_bundle.h"
40 #include "ui/base/webui/jstemplate_builder.h"
41 #include "ui/base/webui/web_ui_util.h"
43 using content::BrowserThread;
44 using content::WebContents;
45 using content::WebUIMessageHandler;
47 namespace {
49 // JS API callbacks names.
50 const char kJsApiCancel[] = "cancel";
51 const char kJsApiChangePinCode[] = "changePinCode";
52 const char kJsApiEnterPinCode[] = "enterPinCode";
53 const char kJsApiEnterPukCode[] = "enterPukCode";
54 const char kJsApiProceedToPukInput[] = "proceedToPukInput";
55 const char kJsApiSimStatusInitialize[] = "simStatusInitialize";
57 // Page JS API function names.
58 const char kJsApiSimStatusChanged[] = "mobile.SimUnlock.simStateChanged";
60 // SIM state variables which are passed to the page.
61 const char kState[] = "state";
62 const char kError[] = "error";
63 const char kTriesLeft[] = "tries";
65 // Error constants, passed to the page.
66 const char kErrorPin[] = "incorrectPin";
67 const char kErrorOk[] = "ok";
69 chromeos::NetworkDeviceHandler* GetNetworkDeviceHandler() {
70 return chromeos::NetworkHandler::Get()->network_device_handler();
73 chromeos::NetworkStateHandler* GetNetworkStateHandler() {
74 return chromeos::NetworkHandler::Get()->network_state_handler();
77 } // namespace
79 namespace chromeos {
81 class SimUnlockUIHTMLSource : public content::URLDataSource {
82 public:
83 SimUnlockUIHTMLSource();
85 // content::URLDataSource implementation.
86 virtual std::string GetSource() const OVERRIDE;
87 virtual void StartDataRequest(
88 const std::string& path,
89 int render_process_id,
90 int render_frame_id,
91 const content::URLDataSource::GotDataCallback& callback) OVERRIDE;
92 virtual std::string GetMimeType(const std::string&) const OVERRIDE {
93 return "text/html";
95 virtual bool ShouldAddContentSecurityPolicy() const OVERRIDE {
96 return false;
99 private:
100 virtual ~SimUnlockUIHTMLSource() {}
102 std::string service_path_;
103 DISALLOW_COPY_AND_ASSIGN(SimUnlockUIHTMLSource);
106 // The handler for Javascript messages related to the "sim-unlock" view.
107 class SimUnlockHandler : public WebUIMessageHandler,
108 public base::SupportsWeakPtr<SimUnlockHandler>,
109 public NetworkStateHandlerObserver {
110 public:
111 SimUnlockHandler();
112 virtual ~SimUnlockHandler();
114 // WebUIMessageHandler implementation.
115 virtual void RegisterMessages() OVERRIDE;
117 // NetworkStateHandlerObserver implementation.
118 virtual void DeviceListChanged() OVERRIDE;
120 private:
121 // Should keep this state enum in sync with similar one in JS code.
122 // SIM_NOT_LOCKED_ASK_PIN - SIM card is not locked but we ask user
123 // for PIN input because PinRequired preference change was requested.
124 // SIM_NOT_LOCKED_CHANGE_PIN - SIM card is not locked, ask user for old PIN
125 // and new PIN to change it.
126 typedef enum SimUnlockState {
127 SIM_UNLOCK_LOADING = -1,
128 SIM_ABSENT_NOT_LOCKED = 0,
129 SIM_NOT_LOCKED_ASK_PIN = 1,
130 SIM_NOT_LOCKED_CHANGE_PIN = 2,
131 SIM_LOCKED_PIN = 3,
132 SIM_LOCKED_NO_PIN_TRIES_LEFT = 4,
133 SIM_LOCKED_PUK = 5,
134 SIM_LOCKED_NO_PUK_TRIES_LEFT = 6,
135 SIM_DISABLED = 7,
136 } SimUnlockState;
138 // Type of the SIM unlock code.
139 enum SimUnlockCode {
140 CODE_PIN,
141 CODE_PUK
144 enum PinOperationError {
145 PIN_ERROR_NONE = 0,
146 PIN_ERROR_UNKNOWN = 1,
147 PIN_ERROR_INCORRECT_CODE = 2,
148 PIN_ERROR_BLOCKED = 3
151 class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> {
152 public:
153 explicit TaskProxy(const base::WeakPtr<SimUnlockHandler>& handler)
154 : handler_(handler),
155 code_type_() {
158 TaskProxy(const base::WeakPtr<SimUnlockHandler>& handler,
159 const std::string& code,
160 SimUnlockCode code_type)
161 : handler_(handler),
162 code_(code),
163 code_type_(code_type) {
166 void HandleCancel() {
167 if (handler_)
168 handler_->CancelDialog();
171 void HandleEnterCode() {
172 if (handler_)
173 handler_->EnterCode(code_, code_type_);
176 void HandleInitialize() {
177 if (handler_)
178 handler_->InitializeSimStatus();
181 void HandleProceedToPukInput() {
182 if (handler_)
183 handler_->ProceedToPukInput();
186 private:
187 friend class base::RefCountedThreadSafe<TaskProxy>;
189 ~TaskProxy() {}
191 base::WeakPtr<SimUnlockHandler> handler_;
193 // Pending code input (PIN/PUK).
194 std::string code_;
196 // Pending code type.
197 SimUnlockCode code_type_;
199 DISALLOW_COPY_AND_ASSIGN(TaskProxy);
202 // Returns the cellular device that this dialog currently corresponds to.
203 const DeviceState* GetCellularDevice();
205 // Processing for the cases when dialog was cancelled.
206 void CancelDialog();
208 // Pass PIN/PUK code to shill and check status.
209 void EnterCode(const std::string& code, SimUnlockCode code_type);
211 // Methods to invoke shill PIN/PUK D-Bus operations.
212 void ChangeRequirePin(bool require_pin, const std::string& pin);
213 void EnterPin(const std::string& pin);
214 void ChangePin(const std::string& old_pin, const std::string& new_pin);
215 void UnblockPin(const std::string& puk, const std::string& new_pin);
216 void PinOperationSuccessCallback(const std::string& operation_name);
217 void PinOperationErrorCallback(const std::string& operation_name,
218 const std::string& error_name,
219 scoped_ptr<base::DictionaryValue> error_data);
221 // Called when an asynchronous PIN operation has completed.
222 void OnPinOperationCompleted(PinOperationError error);
224 // Single handler for PIN/PUK code operations.
225 void HandleEnterCode(SimUnlockCode code_type, const std::string& code);
227 // Handlers for JS WebUI messages.
228 void HandleCancel(const base::ListValue* args);
229 void HandleChangePinCode(const base::ListValue* args);
230 void HandleEnterPinCode(const base::ListValue* args);
231 void HandleEnterPukCode(const base::ListValue* args);
232 void HandleProceedToPukInput(const base::ListValue* args);
233 void HandleSimStatusInitialize(const base::ListValue* args);
235 // Initialize current SIM card status, passes that to page.
236 void InitializeSimStatus();
238 // Notifies SIM Security tab handler that RequirePin preference change
239 // has been ended (either updated or cancelled).
240 void NotifyOnRequirePinChangeEnded(bool new_value);
242 // Notifies observers that the EnterPin or EnterPuk dialog has been
243 // completed (either cancelled or with entry of PIN/PUK).
244 void NotifyOnEnterPinEnded(bool cancelled);
246 // Checks whether SIM card is in PUK locked state and proceeds to PUK input.
247 void ProceedToPukInput();
249 // Processes current SIM card state and update internal state/page.
250 void ProcessSimCardState(const DeviceState* cellular);
252 // Updates page with the current state/SIM card info/error.
253 void UpdatePage(const DeviceState* cellular, const std::string& error_msg);
255 // Dialog internal state.
256 SimUnlockState state_;
258 // Path of the Cellular device that we monitor property updates from.
259 std::string cellular_device_path_;
261 // Type of the dialog: generic unlock/change pin/change PinRequire.
262 SimDialogDelegate::SimDialogMode dialog_mode_;
264 // New PIN value for the case when we unblock SIM card or change PIN.
265 std::string new_pin_;
267 // The initial lock type value, used to observe changes to lock status;
268 std::string sim_lock_type_;
270 // True if there's a pending PIN operation.
271 // That means that SIM lock state change will be received 2 times:
272 // OnNetworkDeviceSimLockChanged and OnPinOperationCompleted.
273 // First one should be ignored.
274 bool pending_pin_operation_;
276 base::WeakPtrFactory<SimUnlockHandler> weak_ptr_factory_;
278 DISALLOW_COPY_AND_ASSIGN(SimUnlockHandler);
281 // SimUnlockUIHTMLSource -------------------------------------------------------
283 SimUnlockUIHTMLSource::SimUnlockUIHTMLSource() {
286 std::string SimUnlockUIHTMLSource::GetSource() const {
287 return chrome::kChromeUISimUnlockHost;
290 void SimUnlockUIHTMLSource::StartDataRequest(
291 const std::string& path,
292 int render_process_id,
293 int render_frame_id,
294 const content::URLDataSource::GotDataCallback& callback) {
295 base::DictionaryValue strings;
296 strings.SetString("title",
297 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_ENTER_PIN_TITLE));
298 strings.SetString("ok", l10n_util::GetStringUTF16(IDS_OK));
299 strings.SetString("cancel", l10n_util::GetStringUTF16(IDS_CANCEL));
300 strings.SetString("enterPinTitle",
301 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_ENTER_PIN_TITLE));
302 strings.SetString("enterPinMessage",
303 l10n_util::GetStringUTF16(IDS_SIM_ENTER_PIN_MESSAGE));
304 strings.SetString("enterPinTriesMessage",
305 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_ENTER_PIN_TRIES_MESSAGE));
306 strings.SetString("incorrectPinTriesMessage",
307 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_INCORRECT_PIN_TRIES_MESSAGE));
308 strings.SetString("incorrectPinTitle",
309 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_INCORRECT_PIN_TITLE));
310 // TODO(nkostylev): Pass carrier name if we know that.
311 strings.SetString("noPinTriesLeft", l10n_util::GetStringFUTF16(
312 IDS_SIM_UNLOCK_NO_PIN_TRIES_LEFT_MESSAGE,
313 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_DEFAULT_CARRIER)));
314 strings.SetString("enterPukButton",
315 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_ENTER_PUK_BUTTON));
316 strings.SetString("enterPukTitle",
317 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_ENTER_PUK_TITLE));
318 strings.SetString("enterPukWarning",
319 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_ENTER_PUK_WARNING));
320 // TODO(nkostylev): Pass carrier name if we know that.
321 strings.SetString("enterPukMessage", l10n_util::GetStringFUTF16(
322 IDS_SIM_UNLOCK_ENTER_PUK_MESSAGE,
323 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_DEFAULT_CARRIER)));
324 strings.SetString("choosePinTitle",
325 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_CHOOSE_PIN_TITLE));
326 strings.SetString("choosePinMessage",
327 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_CHOOSE_PIN_MESSAGE));
328 strings.SetString("newPin", l10n_util::GetStringUTF16(
329 IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_CHANGE_PIN_NEW_PIN));
330 strings.SetString("retypeNewPin", l10n_util::GetStringUTF16(
331 IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_CHANGE_PIN_RETYPE_PIN));
332 strings.SetString("pinsDontMatchMessage", l10n_util::GetStringUTF16(
333 IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_PINS_DONT_MATCH_ERROR));
334 strings.SetString("noPukTriesLeft",
335 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_NO_PUK_TRIES_LEFT_MESSAGE));
336 strings.SetString("simDisabledTitle",
337 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_SIM_DISABLED_TITLE));
338 strings.SetString("simDisabledMessage",
339 l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_SIM_DISABLED_MESSAGE));
341 strings.SetString("changePinTitle", l10n_util::GetStringUTF16(
342 IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_CHANGE_PIN_TITLE));
343 strings.SetString("changePinMessage", l10n_util::GetStringUTF16(
344 IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_CHANGE_PIN_MESSAGE));
345 strings.SetString("oldPin", l10n_util::GetStringUTF16(
346 IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_CHANGE_PIN_OLD_PIN));
348 webui::SetFontAndTextDirection(&strings);
350 static const base::StringPiece html(
351 ResourceBundle::GetSharedInstance().GetRawDataResource(
352 IDR_SIM_UNLOCK_HTML));
354 std::string full_html = webui::GetI18nTemplateHtml(html, &strings);
356 callback.Run(base::RefCountedString::TakeString(&full_html));
359 // SimUnlockHandler ------------------------------------------------------------
361 SimUnlockHandler::SimUnlockHandler()
362 : state_(SIM_UNLOCK_LOADING),
363 dialog_mode_(SimDialogDelegate::SIM_DIALOG_UNLOCK),
364 pending_pin_operation_(false),
365 weak_ptr_factory_(this) {
366 if (GetNetworkStateHandler()
367 ->GetTechnologyState(NetworkTypePattern::Cellular()) !=
368 NetworkStateHandler::TECHNOLOGY_UNAVAILABLE)
369 GetNetworkStateHandler()->AddObserver(this, FROM_HERE);
372 SimUnlockHandler::~SimUnlockHandler() {
373 GetNetworkStateHandler()->RemoveObserver(this, FROM_HERE);
376 void SimUnlockHandler::RegisterMessages() {
377 web_ui()->RegisterMessageCallback(kJsApiCancel,
378 base::Bind(&SimUnlockHandler::HandleCancel,
379 base::Unretained(this)));
380 web_ui()->RegisterMessageCallback(kJsApiChangePinCode,
381 base::Bind(&SimUnlockHandler::HandleChangePinCode,
382 base::Unretained(this)));
383 web_ui()->RegisterMessageCallback(kJsApiEnterPinCode,
384 base::Bind(&SimUnlockHandler::HandleEnterPinCode,
385 base::Unretained(this)));
386 web_ui()->RegisterMessageCallback(kJsApiEnterPukCode,
387 base::Bind(&SimUnlockHandler::HandleEnterPukCode,
388 base::Unretained(this)));
389 web_ui()->RegisterMessageCallback(kJsApiProceedToPukInput,
390 base::Bind(&SimUnlockHandler::HandleProceedToPukInput,
391 base::Unretained(this)));
392 web_ui()->RegisterMessageCallback(kJsApiSimStatusInitialize,
393 base::Bind(&SimUnlockHandler::HandleSimStatusInitialize,
394 base::Unretained(this)));
397 void SimUnlockHandler::DeviceListChanged() {
398 const DeviceState* cellular_device = GetCellularDevice();
399 if (!cellular_device) {
400 LOG(WARNING) << "Cellular device with path '" << cellular_device_path_
401 << "' disappeared.";
402 ProcessSimCardState(NULL);
403 return;
406 // Process the SIM card state only if the lock state changed.
407 if (cellular_device->sim_lock_type() == sim_lock_type_)
408 return;
410 sim_lock_type_ = cellular_device->sim_lock_type();
411 uint32 retries_left = cellular_device->sim_retries_left();
412 VLOG(1) << "OnNetworkDeviceSimLockChanged, lock: " << sim_lock_type_
413 << ", retries: " << retries_left;
414 // There's a pending PIN operation.
415 // Wait for it to finish and refresh state then.
416 if (!pending_pin_operation_)
417 ProcessSimCardState(cellular_device);
420 void SimUnlockHandler::OnPinOperationCompleted(PinOperationError error) {
421 pending_pin_operation_ = false;
422 VLOG(1) << "OnPinOperationCompleted, error: " << error;
423 const DeviceState* cellular = GetCellularDevice();
424 if (!cellular) {
425 VLOG(1) << "Cellular device disappeared. Dismissing dialog.";
426 ProcessSimCardState(NULL);
427 return;
429 if (state_ == SIM_NOT_LOCKED_ASK_PIN && error == PIN_ERROR_NONE) {
430 CHECK(dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON ||
431 dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_OFF);
432 // Async change RequirePin operation has finished OK.
433 NotifyOnRequirePinChangeEnded(
434 dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON);
435 // Dialog will close itself.
436 state_ = SIM_ABSENT_NOT_LOCKED;
437 } else if (state_ == SIM_NOT_LOCKED_CHANGE_PIN && error == PIN_ERROR_NONE) {
438 CHECK(dialog_mode_ == SimDialogDelegate::SIM_DIALOG_CHANGE_PIN);
439 // Dialog will close itself.
440 state_ = SIM_ABSENT_NOT_LOCKED;
442 // If previous EnterPIN was last PIN attempt and SIMLock state was already
443 // processed by OnNetworkDeviceChanged, let dialog stay on
444 // NO_PIN_RETRIES_LEFT step.
445 if (!(state_ == SIM_LOCKED_NO_PIN_TRIES_LEFT && error == PIN_ERROR_BLOCKED))
446 ProcessSimCardState(cellular);
447 if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_UNLOCK &&
448 state_ == SIM_ABSENT_NOT_LOCKED)
449 NotifyOnEnterPinEnded(false);
452 const DeviceState* SimUnlockHandler::GetCellularDevice() {
453 return GetNetworkStateHandler()->GetDeviceState(cellular_device_path_);
456 void SimUnlockHandler::CancelDialog() {
457 if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON ||
458 dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_OFF) {
459 // When async change RequirePin operation is performed,
460 // dialog UI controls such as Cancel button are disabled.
461 // If dialog was cancelled that means RequirePin preference hasn't been
462 // changed and is not in process of changing at the moment.
463 NotifyOnRequirePinChangeEnded(
464 !(dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON));
465 } else if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_UNLOCK) {
466 NotifyOnEnterPinEnded(true);
470 void SimUnlockHandler::EnterCode(const std::string& code,
471 SimUnlockCode code_type) {
472 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
474 pending_pin_operation_ = true;
476 switch (code_type) {
477 case CODE_PIN:
478 if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON ||
479 dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_OFF) {
480 if (!sim_lock_type_.empty()) {
481 // If SIM is locked/absent, change RequirePin UI is not accessible.
482 NOTREACHED() <<
483 "Changing RequirePin pref on locked / uninitialized SIM.";
485 ChangeRequirePin(
486 dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON,
487 code);
488 } else if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_CHANGE_PIN) {
489 if (!sim_lock_type_.empty()) {
490 // If SIM is locked/absent, changing PIN UI is not accessible.
491 NOTREACHED() << "Changing PIN on locked / uninitialized SIM.";
493 ChangePin(code, new_pin_);
494 } else {
495 EnterPin(code);
497 break;
498 case CODE_PUK:
499 DCHECK(!new_pin_.empty());
500 UnblockPin(code, new_pin_);
501 break;
505 void SimUnlockHandler::ChangeRequirePin(bool require_pin,
506 const std::string& pin) {
507 const DeviceState* cellular = GetCellularDevice();
508 if (!cellular) {
509 NOTREACHED() << "Calling RequirePin method w/o cellular device.";
510 return;
512 std::string operation_name = "ChangeRequirePin";
513 NET_LOG_USER(operation_name, cellular->path());
514 GetNetworkDeviceHandler()->RequirePin(
515 cellular->path(),
516 require_pin,
517 pin,
518 base::Bind(&SimUnlockHandler::PinOperationSuccessCallback,
519 weak_ptr_factory_.GetWeakPtr(),
520 operation_name),
521 base::Bind(&SimUnlockHandler::PinOperationErrorCallback,
522 weak_ptr_factory_.GetWeakPtr(),
523 operation_name));
526 void SimUnlockHandler::EnterPin(const std::string& pin) {
527 const DeviceState* cellular = GetCellularDevice();
528 if (!cellular) {
529 NOTREACHED() << "Calling RequirePin method w/o cellular device.";
530 return;
532 std::string operation_name = "EnterPin";
533 NET_LOG_USER(operation_name, cellular->path());
534 GetNetworkDeviceHandler()->EnterPin(
535 cellular->path(),
536 pin,
537 base::Bind(&SimUnlockHandler::PinOperationSuccessCallback,
538 weak_ptr_factory_.GetWeakPtr(),
539 operation_name),
540 base::Bind(&SimUnlockHandler::PinOperationErrorCallback,
541 weak_ptr_factory_.GetWeakPtr(),
542 operation_name));
545 void SimUnlockHandler::ChangePin(const std::string& old_pin,
546 const std::string& new_pin) {
547 const DeviceState* cellular = GetCellularDevice();
548 if (!cellular) {
549 NOTREACHED() << "Calling RequirePin method w/o cellular device.";
550 return;
552 std::string operation_name = "ChangePin";
553 NET_LOG_USER(operation_name, cellular->path());
554 GetNetworkDeviceHandler()->ChangePin(
555 cellular->path(),
556 old_pin,
557 new_pin,
558 base::Bind(&SimUnlockHandler::PinOperationSuccessCallback,
559 weak_ptr_factory_.GetWeakPtr(),
560 operation_name),
561 base::Bind(&SimUnlockHandler::PinOperationErrorCallback,
562 weak_ptr_factory_.GetWeakPtr(),
563 operation_name));
566 void SimUnlockHandler::UnblockPin(const std::string& puk,
567 const std::string& new_pin) {
568 const DeviceState* cellular = GetCellularDevice();
569 if (!cellular) {
570 NOTREACHED() << "Calling RequirePin method w/o cellular device.";
571 return;
573 std::string operation_name = "UnblockPin";
574 NET_LOG_USER(operation_name, cellular->path());
575 GetNetworkDeviceHandler()->UnblockPin(
576 cellular->path(),
577 puk,
578 new_pin,
579 base::Bind(&SimUnlockHandler::PinOperationSuccessCallback,
580 weak_ptr_factory_.GetWeakPtr(),
581 operation_name),
582 base::Bind(&SimUnlockHandler::PinOperationErrorCallback,
583 weak_ptr_factory_.GetWeakPtr(),
584 operation_name));
587 void SimUnlockHandler::PinOperationSuccessCallback(
588 const std::string& operation_name) {
589 NET_LOG_DEBUG("Pin operation successful.", operation_name);
590 OnPinOperationCompleted(PIN_ERROR_NONE);
593 void SimUnlockHandler::PinOperationErrorCallback(
594 const std::string& operation_name,
595 const std::string& error_name,
596 scoped_ptr<base::DictionaryValue> error_data) {
597 NET_LOG_ERROR("Pin operation failed: " + error_name, operation_name);
598 PinOperationError pin_error;
599 if (error_name == NetworkDeviceHandler::kErrorIncorrectPin ||
600 error_name == NetworkDeviceHandler::kErrorPinRequired)
601 pin_error = PIN_ERROR_INCORRECT_CODE;
602 else if (error_name == NetworkDeviceHandler::kErrorPinBlocked)
603 pin_error = PIN_ERROR_BLOCKED;
604 else
605 pin_error = PIN_ERROR_UNKNOWN;
606 OnPinOperationCompleted(pin_error);
609 void SimUnlockHandler::NotifyOnEnterPinEnded(bool cancelled) {
610 content::NotificationService::current()->Notify(
611 chrome::NOTIFICATION_ENTER_PIN_ENDED,
612 content::NotificationService::AllSources(),
613 content::Details<bool>(&cancelled));
616 void SimUnlockHandler::NotifyOnRequirePinChangeEnded(bool new_value) {
617 content::NotificationService::current()->Notify(
618 chrome::NOTIFICATION_REQUIRE_PIN_SETTING_CHANGE_ENDED,
619 content::NotificationService::AllSources(),
620 content::Details<bool>(&new_value));
623 void SimUnlockHandler::HandleCancel(const base::ListValue* args) {
624 const size_t kEnterCodeParamCount = 0;
625 if (args->GetSize() != kEnterCodeParamCount) {
626 NOTREACHED();
627 return;
629 scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr());
630 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
631 base::Bind(&TaskProxy::HandleCancel, task.get()));
634 void SimUnlockHandler::HandleChangePinCode(const base::ListValue* args) {
635 const size_t kChangePinParamCount = 2;
636 std::string pin;
637 std::string new_pin;
638 if (args->GetSize() != kChangePinParamCount ||
639 !args->GetString(0, &pin) ||
640 !args->GetString(1, &new_pin)) {
641 NOTREACHED();
642 return;
644 new_pin_ = new_pin;
645 HandleEnterCode(CODE_PIN, pin);
648 void SimUnlockHandler::HandleEnterCode(SimUnlockCode code_type,
649 const std::string& code) {
650 scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), code, code_type);
651 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
652 base::Bind(&TaskProxy::HandleEnterCode, task.get()));
655 void SimUnlockHandler::HandleEnterPinCode(const base::ListValue* args) {
656 const size_t kEnterPinParamCount = 1;
657 std::string pin;
658 if (args->GetSize() != kEnterPinParamCount || !args->GetString(0, &pin)) {
659 NOTREACHED();
660 return;
662 HandleEnterCode(CODE_PIN, pin);
665 void SimUnlockHandler::HandleEnterPukCode(const base::ListValue* args) {
666 const size_t kEnterPukParamCount = 2;
667 std::string puk;
668 std::string new_pin;
669 if (args->GetSize() != kEnterPukParamCount ||
670 !args->GetString(0, &puk) ||
671 !args->GetString(1, &new_pin)) {
672 NOTREACHED();
673 return;
675 new_pin_ = new_pin;
676 HandleEnterCode(CODE_PUK, puk);
679 void SimUnlockHandler::HandleProceedToPukInput(const base::ListValue* args) {
680 const size_t kProceedToPukInputParamCount = 0;
681 if (args->GetSize() != kProceedToPukInputParamCount) {
682 NOTREACHED();
683 return;
685 scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr());
686 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
687 base::Bind(&TaskProxy::HandleProceedToPukInput, task.get()));
690 void SimUnlockHandler::HandleSimStatusInitialize(const base::ListValue* args) {
691 const size_t kSimStatusInitializeParamCount = 1;
692 double mode;
693 if (args->GetSize() != kSimStatusInitializeParamCount ||
694 !args->GetDouble(0, &mode)) {
695 NOTREACHED();
696 return;
698 dialog_mode_ = static_cast<SimDialogDelegate::SimDialogMode>(mode);
699 VLOG(1) << "Initializing SIM dialog in mode: " << dialog_mode_;
700 scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr());
701 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
702 base::Bind(&TaskProxy::HandleInitialize, task.get()));
705 void SimUnlockHandler::InitializeSimStatus() {
706 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
707 // TODO(armansito): For now, we're initializing the device path to the first
708 // available cellular device. We should try to obtain a specific device here,
709 // as there can be multiple cellular devices present.
710 const DeviceState* cellular_device =
711 GetNetworkStateHandler()
712 ->GetDeviceStateByType(NetworkTypePattern::Cellular());
713 if (cellular_device) {
714 cellular_device_path_ = cellular_device->path();
715 sim_lock_type_ = cellular_device->sim_lock_type();
717 ProcessSimCardState(cellular_device);
720 void SimUnlockHandler::ProceedToPukInput() {
721 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
722 ProcessSimCardState(GetCellularDevice());
725 void SimUnlockHandler::ProcessSimCardState(
726 const DeviceState* cellular) {
727 std::string error_msg;
728 if (cellular) {
729 uint32 retries_left = cellular->sim_retries_left();
730 VLOG(1) << "Current state: " << state_ << " lock_type: " << sim_lock_type_
731 << " retries: " << retries_left;
732 switch (state_) {
733 case SIM_UNLOCK_LOADING:
734 if (sim_lock_type_ == shill::kSIMLockPin) {
735 state_ = SIM_LOCKED_PIN;
736 } else if (sim_lock_type_ == shill::kSIMLockPuk) {
737 if (retries_left > 0)
738 state_ = SIM_LOCKED_PUK;
739 else
740 state_ = SIM_DISABLED;
741 } else if (sim_lock_type_.empty()) {
742 if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON ||
743 dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_OFF) {
744 state_ = SIM_NOT_LOCKED_ASK_PIN;
745 } else if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_CHANGE_PIN) {
746 state_ = SIM_NOT_LOCKED_CHANGE_PIN;
747 } else {
748 state_ = SIM_ABSENT_NOT_LOCKED;
750 } else {
751 // SIM_UNKNOWN: when SIM status is not initialized (should not happen,
752 // since this UI is accessible when SIM is initialized)
753 // or SIM card is absent. In latter case just close dialog.
754 state_ = SIM_ABSENT_NOT_LOCKED;
756 break;
757 case SIM_ABSENT_NOT_LOCKED:
758 // Dialog will close itself in this case.
759 break;
760 case SIM_NOT_LOCKED_ASK_PIN:
761 case SIM_NOT_LOCKED_CHANGE_PIN:
762 // We always start in these states when SIM is unlocked.
763 // So if we get here while still being UNLOCKED,
764 // that means entered PIN was incorrect.
765 if (sim_lock_type_.empty()) {
766 error_msg = kErrorPin;
767 } else if (sim_lock_type_ == shill::kSIMLockPuk) {
768 state_ = SIM_LOCKED_NO_PIN_TRIES_LEFT;
769 } else {
770 NOTREACHED()
771 << "Change PIN / Set lock mode with unexpected SIM lock state";
772 state_ = SIM_ABSENT_NOT_LOCKED;
774 break;
775 case SIM_LOCKED_PIN:
776 if (sim_lock_type_ == shill::kSIMLockPuk) {
777 state_ = SIM_LOCKED_NO_PIN_TRIES_LEFT;
778 } else if (sim_lock_type_ == shill::kSIMLockPin) {
779 // Still locked with PIN.
780 error_msg = kErrorPin;
781 } else {
782 state_ = SIM_ABSENT_NOT_LOCKED;
784 break;
785 case SIM_LOCKED_NO_PIN_TRIES_LEFT:
786 // Proceed user to PUK input.
787 state_ = SIM_LOCKED_PUK;
788 break;
789 case SIM_LOCKED_PUK:
790 if (sim_lock_type_ != shill::kSIMLockPin &&
791 sim_lock_type_ != shill::kSIMLockPuk) {
792 state_ = SIM_ABSENT_NOT_LOCKED;
793 } else if (retries_left == 0) {
794 state_ = SIM_LOCKED_NO_PUK_TRIES_LEFT;
796 // Otherwise SIM card is still locked with PUK code.
797 // Dialog will display enter PUK screen with an updated retries count.
798 break;
799 case SIM_LOCKED_NO_PUK_TRIES_LEFT:
800 case SIM_DISABLED:
801 // User will close dialog manually.
802 break;
804 } else {
805 VLOG(1) << "Cellular device is absent.";
806 // No cellular device, should close dialog.
807 state_ = SIM_ABSENT_NOT_LOCKED;
809 VLOG(1) << "New state: " << state_;
810 UpdatePage(cellular, error_msg);
813 void SimUnlockHandler::UpdatePage(const DeviceState* cellular,
814 const std::string& error_msg) {
815 base::DictionaryValue sim_dict;
816 if (cellular)
817 sim_dict.SetInteger(kTriesLeft, cellular->sim_retries_left());
818 sim_dict.SetInteger(kState, state_);
819 if (!error_msg.empty())
820 sim_dict.SetString(kError, error_msg);
821 else
822 sim_dict.SetString(kError, kErrorOk);
823 web_ui()->CallJavascriptFunction(kJsApiSimStatusChanged, sim_dict);
826 // SimUnlockUI -----------------------------------------------------------------
828 SimUnlockUI::SimUnlockUI(content::WebUI* web_ui) : WebUIController(web_ui) {
829 SimUnlockHandler* handler = new SimUnlockHandler();
830 web_ui->AddMessageHandler(handler);
831 SimUnlockUIHTMLSource* html_source = new SimUnlockUIHTMLSource();
833 // Set up the chrome://sim-unlock/ source.
834 Profile* profile = Profile::FromWebUI(web_ui);
835 content::URLDataSource::Add(profile, html_source);
838 } // namespace chromeos