This source file includes following definitions.
- GetNetworkDeviceHandler
- GetNetworkStateHandler
- GetMimeType
- ShouldAddContentSecurityPolicy
- code_type_
- code_type_
- HandleCancel
- HandleEnterCode
- HandleInitialize
- HandleProceedToPukInput
- GetSource
- StartDataRequest
- weak_ptr_factory_
- RegisterMessages
- DeviceListChanged
- OnPinOperationCompleted
- GetCellularDevice
- CancelDialog
- EnterCode
- ChangeRequirePin
- EnterPin
- ChangePin
- UnblockPin
- PinOperationSuccessCallback
- PinOperationErrorCallback
- NotifyOnEnterPinEnded
- NotifyOnRequirePinChangeEnded
- HandleCancel
- HandleChangePinCode
- HandleEnterCode
- HandleEnterPinCode
- HandleEnterPukCode
- HandleProceedToPukInput
- HandleSimStatusInitialize
- InitializeSimStatus
- ProceedToPukInput
- ProcessSimCardState
- UpdatePage
#include "chrome/browser/ui/webui/chromeos/sim_unlock_ui.h"
#include <string>
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_piece.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/sim_dialog_delegate.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
#include "chromeos/network/device_state.h"
#include "chromeos/network/network_device_handler.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/network_state_handler_observer.h"
#include "chromeos/network/shill_property_util.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_message_handler.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/webui/jstemplate_builder.h"
#include "ui/base/webui/web_ui_util.h"
using content::BrowserThread;
using content::WebContents;
using content::WebUIMessageHandler;
namespace {
const char kJsApiCancel[] = "cancel";
const char kJsApiChangePinCode[] = "changePinCode";
const char kJsApiEnterPinCode[] = "enterPinCode";
const char kJsApiEnterPukCode[] = "enterPukCode";
const char kJsApiProceedToPukInput[] = "proceedToPukInput";
const char kJsApiSimStatusInitialize[] = "simStatusInitialize";
const char kJsApiSimStatusChanged[] = "mobile.SimUnlock.simStateChanged";
const char kState[] = "state";
const char kError[] = "error";
const char kTriesLeft[] = "tries";
const char kErrorPin[] = "incorrectPin";
const char kErrorOk[] = "ok";
chromeos::NetworkDeviceHandler* GetNetworkDeviceHandler() {
return chromeos::NetworkHandler::Get()->network_device_handler();
}
chromeos::NetworkStateHandler* GetNetworkStateHandler() {
return chromeos::NetworkHandler::Get()->network_state_handler();
}
}
namespace chromeos {
class SimUnlockUIHTMLSource : public content::URLDataSource {
public:
SimUnlockUIHTMLSource();
virtual std::string GetSource() const OVERRIDE;
virtual void StartDataRequest(
const std::string& path,
int render_process_id,
int render_frame_id,
const content::URLDataSource::GotDataCallback& callback) OVERRIDE;
virtual std::string GetMimeType(const std::string&) const OVERRIDE {
return "text/html";
}
virtual bool ShouldAddContentSecurityPolicy() const OVERRIDE {
return false;
}
private:
virtual ~SimUnlockUIHTMLSource() {}
std::string service_path_;
DISALLOW_COPY_AND_ASSIGN(SimUnlockUIHTMLSource);
};
class SimUnlockHandler : public WebUIMessageHandler,
public base::SupportsWeakPtr<SimUnlockHandler>,
public NetworkStateHandlerObserver {
public:
SimUnlockHandler();
virtual ~SimUnlockHandler();
virtual void RegisterMessages() OVERRIDE;
virtual void DeviceListChanged() OVERRIDE;
private:
typedef enum SimUnlockState {
SIM_UNLOCK_LOADING = -1,
SIM_ABSENT_NOT_LOCKED = 0,
SIM_NOT_LOCKED_ASK_PIN = 1,
SIM_NOT_LOCKED_CHANGE_PIN = 2,
SIM_LOCKED_PIN = 3,
SIM_LOCKED_NO_PIN_TRIES_LEFT = 4,
SIM_LOCKED_PUK = 5,
SIM_LOCKED_NO_PUK_TRIES_LEFT = 6,
SIM_DISABLED = 7,
} SimUnlockState;
enum SimUnlockCode {
CODE_PIN,
CODE_PUK
};
enum PinOperationError {
PIN_ERROR_NONE = 0,
PIN_ERROR_UNKNOWN = 1,
PIN_ERROR_INCORRECT_CODE = 2,
PIN_ERROR_BLOCKED = 3
};
class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> {
public:
explicit TaskProxy(const base::WeakPtr<SimUnlockHandler>& handler)
: handler_(handler),
code_type_() {
}
TaskProxy(const base::WeakPtr<SimUnlockHandler>& handler,
const std::string& code,
SimUnlockCode code_type)
: handler_(handler),
code_(code),
code_type_(code_type) {
}
void HandleCancel() {
if (handler_)
handler_->CancelDialog();
}
void HandleEnterCode() {
if (handler_)
handler_->EnterCode(code_, code_type_);
}
void HandleInitialize() {
if (handler_)
handler_->InitializeSimStatus();
}
void HandleProceedToPukInput() {
if (handler_)
handler_->ProceedToPukInput();
}
private:
friend class base::RefCountedThreadSafe<TaskProxy>;
~TaskProxy() {}
base::WeakPtr<SimUnlockHandler> handler_;
std::string code_;
SimUnlockCode code_type_;
DISALLOW_COPY_AND_ASSIGN(TaskProxy);
};
const DeviceState* GetCellularDevice();
void CancelDialog();
void EnterCode(const std::string& code, SimUnlockCode code_type);
void ChangeRequirePin(bool require_pin, const std::string& pin);
void EnterPin(const std::string& pin);
void ChangePin(const std::string& old_pin, const std::string& new_pin);
void UnblockPin(const std::string& puk, const std::string& new_pin);
void PinOperationSuccessCallback(const std::string& operation_name);
void PinOperationErrorCallback(const std::string& operation_name,
const std::string& error_name,
scoped_ptr<base::DictionaryValue> error_data);
void OnPinOperationCompleted(PinOperationError error);
void HandleEnterCode(SimUnlockCode code_type, const std::string& code);
void HandleCancel(const base::ListValue* args);
void HandleChangePinCode(const base::ListValue* args);
void HandleEnterPinCode(const base::ListValue* args);
void HandleEnterPukCode(const base::ListValue* args);
void HandleProceedToPukInput(const base::ListValue* args);
void HandleSimStatusInitialize(const base::ListValue* args);
void InitializeSimStatus();
void NotifyOnRequirePinChangeEnded(bool new_value);
void NotifyOnEnterPinEnded(bool cancelled);
void ProceedToPukInput();
void ProcessSimCardState(const DeviceState* cellular);
void UpdatePage(const DeviceState* cellular, const std::string& error_msg);
SimUnlockState state_;
std::string cellular_device_path_;
SimDialogDelegate::SimDialogMode dialog_mode_;
std::string new_pin_;
std::string sim_lock_type_;
bool pending_pin_operation_;
base::WeakPtrFactory<SimUnlockHandler> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(SimUnlockHandler);
};
SimUnlockUIHTMLSource::SimUnlockUIHTMLSource() {
}
std::string SimUnlockUIHTMLSource::GetSource() const {
return chrome::kChromeUISimUnlockHost;
}
void SimUnlockUIHTMLSource::StartDataRequest(
const std::string& path,
int render_process_id,
int render_frame_id,
const content::URLDataSource::GotDataCallback& callback) {
base::DictionaryValue strings;
strings.SetString("title",
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_ENTER_PIN_TITLE));
strings.SetString("ok", l10n_util::GetStringUTF16(IDS_OK));
strings.SetString("cancel", l10n_util::GetStringUTF16(IDS_CANCEL));
strings.SetString("enterPinTitle",
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_ENTER_PIN_TITLE));
strings.SetString("enterPinMessage",
l10n_util::GetStringUTF16(IDS_SIM_ENTER_PIN_MESSAGE));
strings.SetString("enterPinTriesMessage",
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_ENTER_PIN_TRIES_MESSAGE));
strings.SetString("incorrectPinTriesMessage",
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_INCORRECT_PIN_TRIES_MESSAGE));
strings.SetString("incorrectPinTitle",
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_INCORRECT_PIN_TITLE));
strings.SetString("noPinTriesLeft", l10n_util::GetStringFUTF16(
IDS_SIM_UNLOCK_NO_PIN_TRIES_LEFT_MESSAGE,
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_DEFAULT_CARRIER)));
strings.SetString("enterPukButton",
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_ENTER_PUK_BUTTON));
strings.SetString("enterPukTitle",
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_ENTER_PUK_TITLE));
strings.SetString("enterPukWarning",
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_ENTER_PUK_WARNING));
strings.SetString("enterPukMessage", l10n_util::GetStringFUTF16(
IDS_SIM_UNLOCK_ENTER_PUK_MESSAGE,
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_DEFAULT_CARRIER)));
strings.SetString("choosePinTitle",
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_CHOOSE_PIN_TITLE));
strings.SetString("choosePinMessage",
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_CHOOSE_PIN_MESSAGE));
strings.SetString("newPin", l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_CHANGE_PIN_NEW_PIN));
strings.SetString("retypeNewPin", l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_CHANGE_PIN_RETYPE_PIN));
strings.SetString("pinsDontMatchMessage", l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_PINS_DONT_MATCH_ERROR));
strings.SetString("noPukTriesLeft",
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_NO_PUK_TRIES_LEFT_MESSAGE));
strings.SetString("simDisabledTitle",
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_SIM_DISABLED_TITLE));
strings.SetString("simDisabledMessage",
l10n_util::GetStringUTF16(IDS_SIM_UNLOCK_SIM_DISABLED_MESSAGE));
strings.SetString("changePinTitle", l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_CHANGE_PIN_TITLE));
strings.SetString("changePinMessage", l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_CHANGE_PIN_MESSAGE));
strings.SetString("oldPin", l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_CHANGE_PIN_OLD_PIN));
webui::SetFontAndTextDirection(&strings);
static const base::StringPiece html(
ResourceBundle::GetSharedInstance().GetRawDataResource(
IDR_SIM_UNLOCK_HTML));
std::string full_html = webui::GetI18nTemplateHtml(html, &strings);
callback.Run(base::RefCountedString::TakeString(&full_html));
}
SimUnlockHandler::SimUnlockHandler()
: state_(SIM_UNLOCK_LOADING),
dialog_mode_(SimDialogDelegate::SIM_DIALOG_UNLOCK),
pending_pin_operation_(false),
weak_ptr_factory_(this) {
if (GetNetworkStateHandler()
->GetTechnologyState(NetworkTypePattern::Cellular()) !=
NetworkStateHandler::TECHNOLOGY_UNAVAILABLE)
GetNetworkStateHandler()->AddObserver(this, FROM_HERE);
}
SimUnlockHandler::~SimUnlockHandler() {
GetNetworkStateHandler()->RemoveObserver(this, FROM_HERE);
}
void SimUnlockHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(kJsApiCancel,
base::Bind(&SimUnlockHandler::HandleCancel,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(kJsApiChangePinCode,
base::Bind(&SimUnlockHandler::HandleChangePinCode,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(kJsApiEnterPinCode,
base::Bind(&SimUnlockHandler::HandleEnterPinCode,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(kJsApiEnterPukCode,
base::Bind(&SimUnlockHandler::HandleEnterPukCode,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(kJsApiProceedToPukInput,
base::Bind(&SimUnlockHandler::HandleProceedToPukInput,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(kJsApiSimStatusInitialize,
base::Bind(&SimUnlockHandler::HandleSimStatusInitialize,
base::Unretained(this)));
}
void SimUnlockHandler::DeviceListChanged() {
const DeviceState* cellular_device = GetCellularDevice();
if (!cellular_device) {
LOG(WARNING) << "Cellular device with path '" << cellular_device_path_
<< "' disappeared.";
ProcessSimCardState(NULL);
return;
}
if (cellular_device->sim_lock_type() == sim_lock_type_)
return;
sim_lock_type_ = cellular_device->sim_lock_type();
uint32 retries_left = cellular_device->sim_retries_left();
VLOG(1) << "OnNetworkDeviceSimLockChanged, lock: " << sim_lock_type_
<< ", retries: " << retries_left;
if (!pending_pin_operation_)
ProcessSimCardState(cellular_device);
}
void SimUnlockHandler::OnPinOperationCompleted(PinOperationError error) {
pending_pin_operation_ = false;
VLOG(1) << "OnPinOperationCompleted, error: " << error;
const DeviceState* cellular = GetCellularDevice();
if (!cellular) {
VLOG(1) << "Cellular device disappeared. Dismissing dialog.";
ProcessSimCardState(NULL);
return;
}
if (state_ == SIM_NOT_LOCKED_ASK_PIN && error == PIN_ERROR_NONE) {
CHECK(dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON ||
dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_OFF);
NotifyOnRequirePinChangeEnded(
dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON);
state_ = SIM_ABSENT_NOT_LOCKED;
} else if (state_ == SIM_NOT_LOCKED_CHANGE_PIN && error == PIN_ERROR_NONE) {
CHECK(dialog_mode_ == SimDialogDelegate::SIM_DIALOG_CHANGE_PIN);
state_ = SIM_ABSENT_NOT_LOCKED;
}
if (!(state_ == SIM_LOCKED_NO_PIN_TRIES_LEFT && error == PIN_ERROR_BLOCKED))
ProcessSimCardState(cellular);
if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_UNLOCK &&
state_ == SIM_ABSENT_NOT_LOCKED)
NotifyOnEnterPinEnded(false);
}
const DeviceState* SimUnlockHandler::GetCellularDevice() {
return GetNetworkStateHandler()->GetDeviceState(cellular_device_path_);
}
void SimUnlockHandler::CancelDialog() {
if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON ||
dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_OFF) {
NotifyOnRequirePinChangeEnded(
!(dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON));
} else if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_UNLOCK) {
NotifyOnEnterPinEnded(true);
}
}
void SimUnlockHandler::EnterCode(const std::string& code,
SimUnlockCode code_type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
pending_pin_operation_ = true;
switch (code_type) {
case CODE_PIN:
if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON ||
dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_OFF) {
if (!sim_lock_type_.empty()) {
NOTREACHED() <<
"Changing RequirePin pref on locked / uninitialized SIM.";
}
ChangeRequirePin(
dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON,
code);
} else if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_CHANGE_PIN) {
if (!sim_lock_type_.empty()) {
NOTREACHED() << "Changing PIN on locked / uninitialized SIM.";
}
ChangePin(code, new_pin_);
} else {
EnterPin(code);
}
break;
case CODE_PUK:
DCHECK(!new_pin_.empty());
UnblockPin(code, new_pin_);
break;
}
}
void SimUnlockHandler::ChangeRequirePin(bool require_pin,
const std::string& pin) {
const DeviceState* cellular = GetCellularDevice();
if (!cellular) {
NOTREACHED() << "Calling RequirePin method w/o cellular device.";
return;
}
std::string operation_name = "ChangeRequirePin";
NET_LOG_USER(operation_name, cellular->path());
GetNetworkDeviceHandler()->RequirePin(
cellular->path(),
require_pin,
pin,
base::Bind(&SimUnlockHandler::PinOperationSuccessCallback,
weak_ptr_factory_.GetWeakPtr(),
operation_name),
base::Bind(&SimUnlockHandler::PinOperationErrorCallback,
weak_ptr_factory_.GetWeakPtr(),
operation_name));
}
void SimUnlockHandler::EnterPin(const std::string& pin) {
const DeviceState* cellular = GetCellularDevice();
if (!cellular) {
NOTREACHED() << "Calling RequirePin method w/o cellular device.";
return;
}
std::string operation_name = "EnterPin";
NET_LOG_USER(operation_name, cellular->path());
GetNetworkDeviceHandler()->EnterPin(
cellular->path(),
pin,
base::Bind(&SimUnlockHandler::PinOperationSuccessCallback,
weak_ptr_factory_.GetWeakPtr(),
operation_name),
base::Bind(&SimUnlockHandler::PinOperationErrorCallback,
weak_ptr_factory_.GetWeakPtr(),
operation_name));
}
void SimUnlockHandler::ChangePin(const std::string& old_pin,
const std::string& new_pin) {
const DeviceState* cellular = GetCellularDevice();
if (!cellular) {
NOTREACHED() << "Calling RequirePin method w/o cellular device.";
return;
}
std::string operation_name = "ChangePin";
NET_LOG_USER(operation_name, cellular->path());
GetNetworkDeviceHandler()->ChangePin(
cellular->path(),
old_pin,
new_pin,
base::Bind(&SimUnlockHandler::PinOperationSuccessCallback,
weak_ptr_factory_.GetWeakPtr(),
operation_name),
base::Bind(&SimUnlockHandler::PinOperationErrorCallback,
weak_ptr_factory_.GetWeakPtr(),
operation_name));
}
void SimUnlockHandler::UnblockPin(const std::string& puk,
const std::string& new_pin) {
const DeviceState* cellular = GetCellularDevice();
if (!cellular) {
NOTREACHED() << "Calling RequirePin method w/o cellular device.";
return;
}
std::string operation_name = "UnblockPin";
NET_LOG_USER(operation_name, cellular->path());
GetNetworkDeviceHandler()->UnblockPin(
cellular->path(),
puk,
new_pin,
base::Bind(&SimUnlockHandler::PinOperationSuccessCallback,
weak_ptr_factory_.GetWeakPtr(),
operation_name),
base::Bind(&SimUnlockHandler::PinOperationErrorCallback,
weak_ptr_factory_.GetWeakPtr(),
operation_name));
}
void SimUnlockHandler::PinOperationSuccessCallback(
const std::string& operation_name) {
NET_LOG_DEBUG("Pin operation successful.", operation_name);
OnPinOperationCompleted(PIN_ERROR_NONE);
}
void SimUnlockHandler::PinOperationErrorCallback(
const std::string& operation_name,
const std::string& error_name,
scoped_ptr<base::DictionaryValue> error_data) {
NET_LOG_ERROR("Pin operation failed: " + error_name, operation_name);
PinOperationError pin_error;
if (error_name == NetworkDeviceHandler::kErrorIncorrectPin ||
error_name == NetworkDeviceHandler::kErrorPinRequired)
pin_error = PIN_ERROR_INCORRECT_CODE;
else if (error_name == NetworkDeviceHandler::kErrorPinBlocked)
pin_error = PIN_ERROR_BLOCKED;
else
pin_error = PIN_ERROR_UNKNOWN;
OnPinOperationCompleted(pin_error);
}
void SimUnlockHandler::NotifyOnEnterPinEnded(bool cancelled) {
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_ENTER_PIN_ENDED,
content::NotificationService::AllSources(),
content::Details<bool>(&cancelled));
}
void SimUnlockHandler::NotifyOnRequirePinChangeEnded(bool new_value) {
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_REQUIRE_PIN_SETTING_CHANGE_ENDED,
content::NotificationService::AllSources(),
content::Details<bool>(&new_value));
}
void SimUnlockHandler::HandleCancel(const base::ListValue* args) {
const size_t kEnterCodeParamCount = 0;
if (args->GetSize() != kEnterCodeParamCount) {
NOTREACHED();
return;
}
scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr());
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&TaskProxy::HandleCancel, task.get()));
}
void SimUnlockHandler::HandleChangePinCode(const base::ListValue* args) {
const size_t kChangePinParamCount = 2;
std::string pin;
std::string new_pin;
if (args->GetSize() != kChangePinParamCount ||
!args->GetString(0, &pin) ||
!args->GetString(1, &new_pin)) {
NOTREACHED();
return;
}
new_pin_ = new_pin;
HandleEnterCode(CODE_PIN, pin);
}
void SimUnlockHandler::HandleEnterCode(SimUnlockCode code_type,
const std::string& code) {
scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), code, code_type);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&TaskProxy::HandleEnterCode, task.get()));
}
void SimUnlockHandler::HandleEnterPinCode(const base::ListValue* args) {
const size_t kEnterPinParamCount = 1;
std::string pin;
if (args->GetSize() != kEnterPinParamCount || !args->GetString(0, &pin)) {
NOTREACHED();
return;
}
HandleEnterCode(CODE_PIN, pin);
}
void SimUnlockHandler::HandleEnterPukCode(const base::ListValue* args) {
const size_t kEnterPukParamCount = 2;
std::string puk;
std::string new_pin;
if (args->GetSize() != kEnterPukParamCount ||
!args->GetString(0, &puk) ||
!args->GetString(1, &new_pin)) {
NOTREACHED();
return;
}
new_pin_ = new_pin;
HandleEnterCode(CODE_PUK, puk);
}
void SimUnlockHandler::HandleProceedToPukInput(const base::ListValue* args) {
const size_t kProceedToPukInputParamCount = 0;
if (args->GetSize() != kProceedToPukInputParamCount) {
NOTREACHED();
return;
}
scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr());
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&TaskProxy::HandleProceedToPukInput, task.get()));
}
void SimUnlockHandler::HandleSimStatusInitialize(const base::ListValue* args) {
const size_t kSimStatusInitializeParamCount = 1;
double mode;
if (args->GetSize() != kSimStatusInitializeParamCount ||
!args->GetDouble(0, &mode)) {
NOTREACHED();
return;
}
dialog_mode_ = static_cast<SimDialogDelegate::SimDialogMode>(mode);
VLOG(1) << "Initializing SIM dialog in mode: " << dialog_mode_;
scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr());
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&TaskProxy::HandleInitialize, task.get()));
}
void SimUnlockHandler::InitializeSimStatus() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const DeviceState* cellular_device =
GetNetworkStateHandler()
->GetDeviceStateByType(NetworkTypePattern::Cellular());
if (cellular_device) {
cellular_device_path_ = cellular_device->path();
sim_lock_type_ = cellular_device->sim_lock_type();
}
ProcessSimCardState(cellular_device);
}
void SimUnlockHandler::ProceedToPukInput() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
ProcessSimCardState(GetCellularDevice());
}
void SimUnlockHandler::ProcessSimCardState(
const DeviceState* cellular) {
std::string error_msg;
if (cellular) {
uint32 retries_left = cellular->sim_retries_left();
VLOG(1) << "Current state: " << state_ << " lock_type: " << sim_lock_type_
<< " retries: " << retries_left;
switch (state_) {
case SIM_UNLOCK_LOADING:
if (sim_lock_type_ == shill::kSIMLockPin) {
state_ = SIM_LOCKED_PIN;
} else if (sim_lock_type_ == shill::kSIMLockPuk) {
if (retries_left > 0)
state_ = SIM_LOCKED_PUK;
else
state_ = SIM_DISABLED;
} else if (sim_lock_type_.empty()) {
if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON ||
dialog_mode_ == SimDialogDelegate::SIM_DIALOG_SET_LOCK_OFF) {
state_ = SIM_NOT_LOCKED_ASK_PIN;
} else if (dialog_mode_ == SimDialogDelegate::SIM_DIALOG_CHANGE_PIN) {
state_ = SIM_NOT_LOCKED_CHANGE_PIN;
} else {
state_ = SIM_ABSENT_NOT_LOCKED;
}
} else {
state_ = SIM_ABSENT_NOT_LOCKED;
}
break;
case SIM_ABSENT_NOT_LOCKED:
break;
case SIM_NOT_LOCKED_ASK_PIN:
case SIM_NOT_LOCKED_CHANGE_PIN:
if (sim_lock_type_.empty()) {
error_msg = kErrorPin;
} else if (sim_lock_type_ == shill::kSIMLockPuk) {
state_ = SIM_LOCKED_NO_PIN_TRIES_LEFT;
} else {
NOTREACHED()
<< "Change PIN / Set lock mode with unexpected SIM lock state";
state_ = SIM_ABSENT_NOT_LOCKED;
}
break;
case SIM_LOCKED_PIN:
if (sim_lock_type_ == shill::kSIMLockPuk) {
state_ = SIM_LOCKED_NO_PIN_TRIES_LEFT;
} else if (sim_lock_type_ == shill::kSIMLockPin) {
error_msg = kErrorPin;
} else {
state_ = SIM_ABSENT_NOT_LOCKED;
}
break;
case SIM_LOCKED_NO_PIN_TRIES_LEFT:
state_ = SIM_LOCKED_PUK;
break;
case SIM_LOCKED_PUK:
if (sim_lock_type_ != shill::kSIMLockPin &&
sim_lock_type_ != shill::kSIMLockPuk) {
state_ = SIM_ABSENT_NOT_LOCKED;
} else if (retries_left == 0) {
state_ = SIM_LOCKED_NO_PUK_TRIES_LEFT;
}
break;
case SIM_LOCKED_NO_PUK_TRIES_LEFT:
case SIM_DISABLED:
break;
}
} else {
VLOG(1) << "Cellular device is absent.";
state_ = SIM_ABSENT_NOT_LOCKED;
}
VLOG(1) << "New state: " << state_;
UpdatePage(cellular, error_msg);
}
void SimUnlockHandler::UpdatePage(const DeviceState* cellular,
const std::string& error_msg) {
base::DictionaryValue sim_dict;
if (cellular)
sim_dict.SetInteger(kTriesLeft, cellular->sim_retries_left());
sim_dict.SetInteger(kState, state_);
if (!error_msg.empty())
sim_dict.SetString(kError, error_msg);
else
sim_dict.SetString(kError, kErrorOk);
web_ui()->CallJavascriptFunction(kJsApiSimStatusChanged, sim_dict);
}
SimUnlockUI::SimUnlockUI(content::WebUI* web_ui) : WebUIController(web_ui) {
SimUnlockHandler* handler = new SimUnlockHandler();
web_ui->AddMessageHandler(handler);
SimUnlockUIHTMLSource* html_source = new SimUnlockUIHTMLSource();
Profile* profile = Profile::FromWebUI(web_ui);
content::URLDataSource::Add(profile, html_source);
}
}